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 <[email protected]> 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 <[email protected]
>> <mailto:[email protected]>> 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>
>