Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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.

...