...
A simple C binding for a native client library function would look something like this:
Code Block |
---|
struct CacheFactory; typedef struct CacheFactory CacheFactory; APACHE_GEODE_EXPORT voidCacheFactory* CreateCacheFactory(); APACHE_GEODE_EXPORT DestroyCacheFactory(CacheFactory* factory); |
And be implemented something like this:
Code Block |
---|
voidCacheFactory* CreateCacheFactory() { CacheFactoryWrapper* cacheFactory = new CacheFactoryWrapper(); return reinterpret_cast<CacheFactory*>(cacheFactory); } void destroyCacheFactory(CacheFactory* cacheFactory) { delete reinterpret_cast<CacheFactoryWrapper*>(cacheFactory); } |
Binding to this function and calling it is trivial for most other languages. Here's an example for .net core:
Code Block |
---|
[DllImport(Constants.libPath, CharSet = CharSet.Auto)] private static extern IntPtr CreateCacheFactory(); var containedObjectfactory = CreateCacheFactory(); // Do stuff with factory DestroyCacheFactory(factory); |
And from Python:
Code Block |
---|
from ctypes import cdll, c_void_p
nativeclient_ = cdll.LoadLibrary(
"/Users/build/Workspace/native_client_install/libpivotal-gemfire.dylib"
)
nativeclient_.CreateCacheFactory.restype = c_void_p
nativeclient_.DestroyCacheFactory.argtypes = [c_void_p]
factory_ = self.nativeclient_.CreateCacheFactory()
# Do stuff with factory
self.nativeclient_.DestroyCacheFactory(factory_) |
Other languages follow a similar pattern.
...
We propose to add C bindings of a form similar to the above to the public API for the native client. The new API would need to be fully documented, but we believe implementation can start with coverage of a very small subset of the existing C++ API and still be extremely useful.
Since C functions can't be namespaced, we will adopt a naming convention for the C functions that distinguishes them as best they can be from application code. This will most likely be a string prefix representing the namespace, e.g. "apache_geode_client_CreateCacheFactory".
The C bindings must reside in a shared library or DLL, as required by the method(s) used by various languages to interact with C code. They can either be incorporated into their own library, or compiled into the existing native client library. There is a tradeoff in this decision between ease of use on the part of an end-user and ease of use for developers of language bindings. We will initially use a separate library, and make a final decision after the team has had some experience with the new code and binaries.
Performance Impact
Any performance impact of calling through a C binding should be very minimal. A C function exposing a native client method should only involve a pointer cast and a call to the "wrapped" C++ API. Additionally, there will be no performance impact whatsoever for existing applications, since we're not proposing to modify any of the existing C++ code. Eventually we should be able to benchmark the C vs C++ calls to quantify the performance difference, but this is a fairly low priority. Benchmarking API performance from another language calling through the C bindings is a much more interesting and necessary task, which we believe will be undertaken as part of any future support for said language.
...