On the strongly typed, I found a solution I like even better. struct CacheFactory; typedef struct CacheFactory CacheFactory;
struct Cache; typedef struct Cache Cache; CacheFactory* createCacheFactory() { return reinterpret_cast<CacheFactory*>( new apache::geode::client::CacheFactory()); } void destroyCacheFactory(CacheFactory* cacheFactory) { delete reinterpret_cast<apache::geode::client::CacheFactory*>(cacheFactory); } Cache* createCache(CacheFactory* cacheFactory) { return reinterpret_cast<Cache*>(new apache::geode::client::Cache( reinterpret_cast<apache::geode::client::CacheFactory*>(cacheFactory) ->create())); } void destroyCache(Cache* cache) { delete reinterpret_cast<apache::geode::client::Cache*>(cache); } The code below is type safe and won’t compile. CacheFactory cacheFactory = createCacheFactory(); destroyCache(cacheFactory); -Jake > On Mar 26, 2020, at 12:22 PM, Jacob Barrett <jbarr...@pivotal.io> wrote: > > I am onboard with the idea but I would like more details in the RFC. > > I would prefer that the C bindings be in its own library. The only symbols > that should be visible from this library should be the C exported symbols, > the internal C++ symbols should be hidden. > > I feel like this library makes the most sense as a static library. I saw this > because in .NET we would link it as a mixed mode assembly to avoid having > multiple shared libraries to link. If we did a node client I would expect it > too would statically link this library as into its shared library. Same I > imagine would apply to all other language bindings. > > How are you planning on managing allocation and deallocation of these opaque > void* pointers. You vaguely showed the allocation but deallocation would be a > good example. I would assume some “destroy” method for every “create” method. > > Does it make sense to have the CacheFactory concept at all (especially since > it is more of a builder)? Could we have some C struct that can be used to > create the cache, where the struct has fields for all the configuration? In > general can we rethink the API so that it makes sense for C or other language > bindings? > > What about finding a way to be more expressive than void*. Typedefs at least > express some meaning when hovering but will just decay without warning to the > void*. > > Consider: > typedef void* CacheFactory; > typedef void* Cache; > CacheFactory createCacheFactory(void); > void destroyCacheFactory(CacheFactory cacheFactory); > Cache createCache(CacheFactory cacheFactory); > void destroyCache(Cache cache); > > But this compiles: > CacheFactory cacheFactory = createCacheFactory(); > destroyCache(cacheFactory); > > And explodes at runtime. > Example > https://github.com/pivotal-jbarrett/geode-native/tree/2d7d0a28fb6f85988e7b921fd96ebb975bad8126/ccache > > <https://github.com/pivotal-jbarrett/geode-native/tree/2d7d0a28fb6f85988e7b921fd96ebb975bad8126/ccache> > > We could use structs to hold the opaque pointers, and other values. > typedef struct { > void* ptr; > } CacheFactory; > typedef struct { > void* ptr; > } Cache; > > And now this does not compile: > CacheFactory cacheFactory = createCacheFactory(); > destroyCache(cacheFactory); > Example > https://github.com/pivotal-jbarrett/geode-native/tree/23b44e281fd9771474ff3555020710bf23f454ae/ccache > > <https://github.com/pivotal-jbarrett/geode-native/tree/23b44e281fd9771474ff3555020710bf23f454ae/ccache> > > > -Jake > > >> On Mar 24, 2020, at 2:20 PM, Blake Bender <bben...@pivotal.io >> <mailto:bben...@pivotal.io>> wrote: >> >> Hello everyone, >> >> We'd like to add C bindings to the native client, in preparation for the >> larger task of adding support for new languages, e.g. .net core. Please >> have a look at the proposal below and let me know what you think. >> >> Thanks, >> >> Blake >> >> >> https://cwiki.apache.org/confluence/display/GEODE/Add+C+Bindings+to+Native+Client+Library >> >> <https://cwiki.apache.org/confluence/display/GEODE/Add+C+Bindings+to+Native+Client+Library> >