C# FFI wrapper for the GemStone C Interface (GCI)
GemStone is an object database and Smalltalk application runtime environment. You interact with the database through a dynamically linked C library available for Linux, macOS, and Windows. To use a C library from C# we use the built-in FFI.
GemBuilder for C documentation (HTML or PDF) describes the API for the single-threaded GCI library. We are using a new thread-safe library that has fewer functions (but more features). It is not separately documented, but has a header file, gcits.hf
, that is the definitive specification (a recent copy is included with this checkout).
The needed C libraries are not included as part of this checkout since there is a different set of libraries for each platform (Linux, macOS, and Windows), and for each GemStone version. You should download a recent version and the appropriate product for your platform. Then move the appropriate files into the directory of your choice.
- macOS: libgcits-3.4.x-64.dylib, libkrb5-3.5.0-64.dylib, libssl-3.5.0-64.dylib
To add new function wrappers follow these steps:
- Identify a new function from
gcits.hf
(pick from the list below); - Add it to GciLibrary with the appropriate name, arguments, and return type;
- Add a wrapper function to GciSession to provide a C#-like API;
- Add a test to show that it works; and, finally,
- Submit a pull request!
For inspiration, see GciForPython or GciForJavaScript.
The following provides a list of all the functions defined in gcits.hf
grouped to roughly parallel the tables in the GemBuilder for C manual. Checked items have been completed.
BoolType GciTsAbort(GciSession sess, GciErrSType *err);
BoolType GciTsBegin(GciSession sess, GciErrSType *err);
BoolType GciTsCommit(GciSession sess, GciErrSType *err);
char* GciTsEncrypt(const char* password, char *outBuf, size_t outBuffSize);
int GciTsSessionIsRemote(GciSession sess);
GciSession GciTsLogin(...);
BoolType GciTsLogout(GciSession sess, GciErrSType *err);
BoolType GciTsBreak(GciSession sess, BoolType hard, GciErrSType *err);
int GciTsCallInProgress(GciSession sess, GciErrSType *err);
BoolType GciTsClearStack(GciSession sess, OopType gsProcess, GciErrSType *err);
OopType GciTsContinueWith(GciSession sess, ...);
int GciTsGemTrace(GciSession sess, int enable, GciErrSType *err);
BoolType GciTsReleaseObjs(GciSession sess, OopType *buf, int count, GciErrSType *err);
BoolType GciTsReleaseAllObjs(GciSession sess, GciErrSType *err);
BoolType GciTsSaveObjs(GciSession sess, OopType *buf, int count, GciErrSType *err);
OopType GciTsCompileMethod(GciSession sess, ...);
BoolType GciTsProtectMethods(GciSession sess, BoolType mode, GciErrSType *err);
OopType GciTsExecute(GciSession sess, ...);
OopType GciTsExecute_(GciSession sess, ...);
ssize_t GciTsExecuteFetchBytes(GciSession sess, ...);
OopType GciTsPerform(GciSession sess, ...);
ssize_t GciTsPerformFetchBytes(GciSession sess, ...);
OopType GciTsResolveSymbol(GciSession sess, ...);
OopType GciTsResolveSymbolObj(GciSession sess, ...);
int GciTsGetFreeOops(GciSession sess, OopType *buf, int numOopsRequested, GciErrSType *err);
OopType GciTsNewObj(GciSession sess, OopType aClass, GciErrSType *err);
OopType GciTsNewByteArray(GciSession sess, ...);
OopType GciTsNewString_(GciSession sess, ...);
OopType GciTsNewSymbol(GciSession sess, ...);
OopType GciTsNewUnicodeString_(GciSession sess, ...);
OopType GciTsNewUtf8String_(GciSession sess, ...);
int64 GciTsFetchUnicode(GciSession sess, ...);
BoolType GciTsOopIsSpecial(OopType oop);
OopType GciTsFetchSpecialClass(OopType oop);
int GciTsOopToChar(OopType oop);
OopType GciTsCharToOop(uint ch);
OopType GciTsDoubleToSmallDouble(double aFloat);
OopType GciI32ToOop(int arg);
OopType GciTsDoubleToOop(GciSession sess, double aDouble, GciErrSType *err);
BoolType GciTsOopToDouble(GciSession sess, OopType oop, ...);
OopType GciTsI64ToOop(GciSession sess, int64 arg, GciErrSType *err);
BoolType GciTsOopToI64(GciSession sess, OopType oop, int64 *result, GciErrSType *err);
int GciTsStoreTravDoTravRefs(GciSession sess, ...);
int GciTsFetchTraversal(GciSession sess, ...);
BoolType GciTsStoreTrav(GciSession sess, ...);
int GciTsMoreTraversal(GciSession sess, ...);
int64 GciTsFetchBytes(GciSession sess, ...);
int64 GciTsFetchChars(GciSession sess, ...);
int64 GciTsFetchUtf8Bytes(GciSession sess, ...);
BoolType GciTsStoreBytes(GciSession sess, ...);
int GciTsFetchOops(GciSession sess, ...);
BoolType GciTsStoreOops(GciSession sess, ...);
int GciTsRemoveOopsFromNsc(GciSession sess, ...);
int64 GciTsFetchObjInfo(GciSession sess, OopType objId, ...);
int64 GciTsFetchSize(GciSession sess, OopType obj, GciErrSType *err);
int64 GciTsFetchVaryingSize(GciSession sess, OopType obj, GciErrSType *err);
OopType GciTsFetchClass(GciSession sess, OopType obj, GciErrSType *err);
int GciTsIsKindOf(GciSession sess, ...);
int GciTsIsSubclassOf(GciSession sess, ...);
int GciTsIsKindOfClass(GciSession sess, ...);
int GciTsIsSubclassOfClass(GciSession sess, ...);
BoolType GciTsObjExists(GciSession sess, OopType obj);
โ uint GciTsVersion(char *buf, size_t bufSize);
int GciTsWaitForEvent(GciSession sess, int latencyMs, ...);
BoolType GciTsCancelWaitForEvent(GciSession sess, GciErrSType *err);
GciTs offers a variety of Fork
functions that take a callback. Does C# have its own asychronyous functions?
BoolType GciTsForkLogin(...);
BoolType GciTsForkContinueWith(GciSession sess, ...);
BoolType GciTsForkExecute(GciSession sess, ...);
BoolType GciTsForkPerform(GciSession sess, ...);
BoolType GciTsForkStoreTravDoTravRefs(GciSession sess, ...);
The following are deprecated in favor of the underscore version.
OopType GciTsNewString(GciSession sess, ...);
OopType GciTsNewUnicodeString(GciSession sess, ...);
OopType GciTsNewUtf8String(GciSession sess, ...);
The following provide UTF-8 conversion. Can this be done in C#?
BoolType GciUtf8To8bit(const char* src, char *dest, ssize_t destSize);
ssize_t GciNextUtf8Character(const char* src, size_t len, uint *chOut);
The following did not seem to work but may have been fixed recently.
BoolType GciTsClassRemoveAllMethods(GciSession sess, ...);
int64 GciTsFetchUtf8(GciSession sess, ...);