Syncbase cgo bridge

The Syncbase cgo bridge exposes a C API to Syncbase. It's intended to be used on iOS (Swift) and Android (Java), and perhaps elsewhere as well.

For the time being, we provide a Makefile to build C archives for all target platforms. Eventually, we'll integrate C archive compilation with the jiri tool.

JNI

Java expects functions that have names and arguments that match the native declarations from the .java files located in java/io/v/syncbase/internal.

Layout:

  • jni.go: the JNI functions expected by Java.
  • jni_util.go: helper functions to find Java classes and retrieve IDs for object fields and methods.
  • jni_lib.go: types and functions to cache the field and method IDs for all the classes the code needs to touch.
  • jni_types.go: methods and functions to convert between Java and the types declared in lib.h; counterpart of types.go.
  • jni_wrapper.{h,c}: trampoline functions that compensate for the fact that Go cannot call a function pointer.

Some design notes:

  • looking up classes/interfaces, methods and field IDs is expensive. The global variables named like fooClass from jni.go cache all we need for a class foo. The load is done in JNI_OnLoad, a function that is called each time the our library is loaded (typically, using System.loadLibrary()).
  • some of the extractToJava() methods and newVFoo() functions are in jni.go instead of jni_types.go to avoid some “inconsistent definitions” errors.
  • the extractToJava() methods convert from low-level types like v23_syncbase_Foo to their Java equivalents. The extract() methods convert to Go equivalents. Both extract() and extractToJava() will free all the pointers inside the primitive types they are extracting from.
  • the free() methods are idempotent.
  • we use panic() to enforce certain invariants (enough memory, existence of classes, methods, fields, etc) and to keep the code simple.