Interfacing J With C

Some ways to call a dynamically linked library from J.

Call a (Simple) Dynamic Library From J

These are notes I've taken while exploring this feature for my own enjoyment, and are not necessarily accurate or complete. But, if you're in that in-between space where your needs have outgrown the basic uses of J's DLL features, but you're not quite an expert yet, then this page may help save you some time.

A C Library

void foo(int *x){x[0] += 3;}
int bar(int *a){return a[1];}
int baz(int *a, int b){return a[b];}

Build as a Dynamic Library

Note: using MacOS in this example, so file extension is .dylib.

mkdir -p src/lib
gcc -c src/foobar.c -o src/lib/foobar.o
gcc -dynamiclib src/lib/foobar.o -o src/lib/libfoobar.dylib

Call From J

The cd function returns a list of boxes. The first item is the return value from the foreign function call. The remaining values are the arguments which were given to cd. This seemed pointless to me at first, until I realized that C can't return arrays. Instead, you can pass a pointer to an array, modify the array inside the function, and examine the array after the function returns.

This "modify by reference" behavior is demonstrated by this first example:

a =: <0 1 2
'./src/lib/libfoobar.dylib foo n *i' cd a
│0│3 1 2│

Interestingly, the J value a was not actually changed, indicating that J has a second copy. Perhaps this is what JfC means by "adequate only for simple functions".

a =: <0 1 2
result =: './src/lib/libfoobar.dylib foo n *i' cd a
││0 1 2│││0│3 1 2││

In the next example, the return value is a[1]:

'./src/lib/libfoobar.dylib bar i *i' cd <1 2 3
│2│1 2 3│

Pass multiple arguments to cd as a list of boxes:

'./src/lib/libfoobar.dylib baz i *i i' cd 1 2 3;2
│3│1 2 3│2│


#include <stdio.h>
void print(int* x, int len){printf("( ");for(int i=0;i<len;++i){printf("%d ", x[i]);}printf(")\n");}
gcc -c src/prnt.c -o src/lib/prnt.o
gcc -dynamiclib src/lib/prnt.o -o src/lib/libprnt.dylib

The first line is printed by C, the remaining lines are the return value of the foreign function.

'./src/lib/libprnt.dylib print n *i i' cd a;#a =: 2 4 6
( 2 4 6 )
│0│2 4 6│3│

Using C Structs

Documentation about how to send/receive data to a dll which uses C structs is scarce. However, some J programmers pointed me in the right direction. Thanks to Eric Iverson and "Tangentstorm" for their help!

Begin with a C file with a struct datatype and a function:

struct stuff {double a[2]; int i;};
void fn(struct stuff *x) {x->a[x->i] += 100;}

Compile it as a dynamically linked library:

gcc -c src/s.c -o src/lib/s.o
gcc -dynamiclib src/lib/s.o  -o src/lib/stuff.dylib

Call it from J.

The big difference is that for simple types, J does conversions automatically. But with structs, you have to do the conversions yourself using fc (float convert, 3!:5) and ic (integer convert, 3!:4). These functions convert J floats or integers into a sequence of bytes, or reverse that conversion, depending on the left argument. Basically, the entire struct will be serialized as a char array, and treated as a pointer to char (*c). The last piece of the puzzle is to box the right argument of cd.

a =: 2.3 2.4
i =: 1
s =: (2 fc a), 2 ic i
r =: './src/lib/stuff.dylib fn n *c' cd <s
r =: >1{r
(_2 fc 16{.r)  NB. the first 16 bytes of the struct contain double[2]
(_2 ic _4{.r)  NB. last 4 bytes contain int
2.3 102.4



In this specific case, everything worked out correctly. However, in general, compilers may add padding or alignment to structured data. This depends on the data and compiler settings, and maybe other things such as the system's CPU architecture and operating system.

Bottom line: do not rely on this kind of simplistic serialization if you need reliable cross-platform code.