> E.g. every C++ library should come with an optional C-API to simplify language bindings, or even just compiling that library into a DLL.
hard to do without incurring additional dynamic allocations though. e.g. how would you make, say, an API that wraps construction / doing stuff / destruction of something that'd look like this :
in C you'd likely have to have something that looks like
mylib_node* mylib_node_alloc(void);
void mylib_node_free(mylib_node*);
// and then...
float* mylib_node_value(mylib_node*); // this ?
float mylib_node_value(mylib_node*, int* ok); // or this ?
void mylib_node_set_value(mylib_node*, float value, int set); // then there's this ?
void mylib_node_set_value(mylib_node*, float* value); // or this ?
void mylib_node_unset_value(mylib_node*); // or maybe this ?
and all this cannot really be done without a dynamic allocation (which hopefully looks terrible to everyone), unless you fancy doing ugly ugly ugly stuff like
struct mylib_node { char storage[sizeof c++ struct that was computed manually)]; };
so anything that'd allow other languages to understand at least C++ vocabulary would be a great boon in terms of perf, etc
// Or replace with something like a Strong Type; https://www.fluentcpp.com/2017/05/05/news-strong-types-are-free/
using NodeHandle = int;
struct OptFloat { float Value; bool bInitialized = false; };
NodeHandle CreateNode(NodeHandle* Children, int NumChildren, OptFloat Value);
void DestroyNode(NodeHandle ToDestroy);
void SetValue(NodeHandle ToSet, OptFloat NewValue);
Aside from that, you do raise a good point. If you implemented your C api over your implementation of node, you would be in for a bad time as the owning std::vector<node> won't keep valid your pointers valid.. This isn't suposed to be ragging on your code, it's really to point out the pitfalls of manual APIs.
> struct mylib_node { char storage[sizeof c++ struct that was computed manually)]; };
You can do;
// IN C api, fill this in manually
#define mylib_storagsize = ?
struct mylib_node {char storage[MYLIB_STORAGESIZE]; };
// or;
struct mylib_node {void* storage; }
// in node.cpp - the underlying C++ abstraction;
static_assert(sizeof(mylib::node) == MYLIB_STORAGESIZE);
hard to do without incurring additional dynamic allocations though. e.g. how would you make, say, an API that wraps construction / doing stuff / destruction of something that'd look like this :
in C you'd likely have to have something that looks like and all this cannot really be done without a dynamic allocation (which hopefully looks terrible to everyone), unless you fancy doing ugly ugly ugly stuff like so anything that'd allow other languages to understand at least C++ vocabulary would be a great boon in terms of perf, etc