Guides/Language Bindings

From J Wiki
Jump to navigation Jump to search

If you want to call the other language from J, your best bet is probably to make a shared library (*.so or *.dll) and just call the DLL from J.

This page is about embedding J in another language.

Example Language Bindings

How to make a language binding (Writing a J Frontend)

The basic idea is essentially the same as making a J front end, wrapping j.dll.

The interface is defined in jsrc/jlib.h

bare minimum

At a minimum, you need to wrap the following functions:

CDPROC JS _stdcall JInit(void);                     /* init instance */
CDPROC int _stdcall JDo(JS jt,C*);                  /* run sentence */
CDPROC int _stdcall JFree(JS jt);                   /* free instance */

With these, you can make J do things, but you can't yet observe the state of the system.

fetching and setting variables by name from J

Once you can run J sentences, you can ask for the value of a variable using either JGetA or JGetM.

JGetA gives you a (copy?) of the data as a J array, whereas JGetM gives you a direct reference to the data in memory. (?? I think. Someone please fact check this!)

CDPROC A _stdcall JGetA(JS jt,I n,C* name);         /* get 3!:1 from name */
CDPROC int _stdcall JGetM(JS jt, C* name, I* jtype, I* jrank, I* jshape, I* jdata);

You can set variables either by calling JDo and performing a normal assignment, or using JSetM:

CDPROC int _stdcall JSetM(JS jt, C* name, I* jtype, I* jrank, I* jshape, I* jdata);

JInit creates a new J session. JDo executes a J string, and JFree closes the session when you're done.

Adding I/O

If you want to expose interaction with the J session -- for example, if you want to see the results printed after running a line with JDo -- then you need to pass in some callbacks:

CDPROC void _stdcall JSM(JS jt, void**callbacks);  /* set callbacks */

The signatures for the callbacks are:

void _stdcall Joutput(JS jt, int type, C* s);
int _stdcall Jwd(JS jt, int x, A parg, A* pres, C* loc);
C* _stdcall Jinput(JS jt, C*);

jt is the session token you got from JInit. C* indicates a C string, and A indicates a J array.

Implementing JWd (11!:x)

NOTE: you do not actually need to implement this, but it is a simple way to expose functions from your frontend language to J.

This is a callback for the J Window driver, a predecessor to JQt. The QT IDE is split into an executable and a shared object (jQt.dll on windows), so J can interact with Qt just by calling into the DLL directly. (This is set up in the ide_qt git repo.)

If you don't want to split parts of your application out into a DLL, you can use JWd. (JAndroid still does this, for example.)

The basic idea is that you call (11!:x) y from the J side, where x is a number that represents the host function you want to call, and y is some rank-1 array with the arguments.

You can use whatever numbering system you like, but if you are interested in implementing your own wd or gl2 backend, you might want to mirror the scheme here:

understanding the A struct

The basic structure is documented here:

fields in the A structure
field purpose
k "offset of ravel with respect to byte 0 of the array"
f a flag of some sort (not sure what this is for)
m "maximum number of bytes in ravel"
t the type number (see datatype verb in J)
c the reference count (at least for JWd, this will have a weird high bit set, and you can just ignore the whole field)
n the length of the data
r rank + some other information in the high bits. (just look at the lowest 7 or 8 bits to get the rank)
s a pointer to the shape
v... the ravel (unshaped data of length n)

see also