Initial Release
CNA provides an interface for using native C-compatible shared libraries without anything but Caché ObjectScript code. CNA is a wrapper for libffi. CNA consists of native library (libcna) and Caché class (CNA.CNA).
make libffi
. If ‘make’ says that GLOBALS_HOME
is undefined, then define it: export GLOBALS_HOME='path to Caché root directory'
make
do $system.OBJ.Load("path to cna.xml", "c")
For Windows-based systems you can try to do the same as for Linux (for building you may use mingw32 or mingw32-w64). Or you can just download binary files. Note: types (32-bit or 64-bit) of libcna, current Caché installation and external libraries must be equal.
For building you can use MSYS2.
How to:
pacman -S make, textinfo
pacman -S mingw-w64-x86_64-gcc
pacman -S gcc
cd libs/libffi && ./configure --build=$(BUILDSYS) --enable-shared=no && $(MAKE)
with cd libs/libffi && ./configure --prefix=/mingw --build=$(BUILDSYS) --enable-shared=no && $(MAKE)
If you want to check if CNA works correctly on your system you may run the unit-tests. You will need native library with test functions ‘libtest’. If you build CNA by yourself, it is already in the right place. If no — it must be placed in directory cna/tests/
. Than you should set ^UnitTestRoot
global to the right value and run the tests.
set ^UnitTestRoot="path to 'cna/tests/' directory"
do ##class(%UnitTest.Manager).RunTest()
Let’s try to call strlen
function from C standard library. In Windows it should be located in C:\Windows\System32\msvcrt.dll
. In Linux — /usr/lib/libc.so
. strlen
returns the length of the string:
size_t strlen ( const char * str );
Let’s see what you need to do to call it from Caché:
set cna = ##class(CNA.CNA).%New("path to libcna"); Creates object of CNA.CNA class. do cna.LoadLibrary("path to libc") ; Loads C standard library in CNA
set string = cna.ConvertStringToPointer("Hello") ; Converts the string into char array, and saves pointer to the first element
; That's how string are stored in Cset argTypes = $lb(cna.#POINTER) ; Creates list of CNA.CNA pararmeters. Each parameter stands for the type of the function argument
set result = cna.CallFunction("strlen", ; Passes the name of the function,
cna.#SIZET, ; type of return value,
argTypes, ; list of argument types,
string) ; and comma-separated arguments
write result, ! ; Writes the result (it should be 5)
do cna.FreeLibrary() ; Frees the library