// Wrapper code around the libj DLL. Mostly provides global function pointers
// for the J interaction functions as well as the logic for finding and loading
// the libj shared object.
#include "jnj.h"
#include <dlfcn.h>
#include <janet.h>
#include <stdio.h>
#define UNUSED __attribute__((unused))
#ifdef __MACH__
#define LIBJ "libj.dylib"
#endif
#ifdef _WIN32
#define LIBJ "libj.dll"
#endif
#ifdef __linux__
#define LIBJ "libj.so"
#endif
/// Callbacks
static V JOutput(UNUSED V *jt, int type, C *s) {
printf("J:\n\tType: %i\n\tOutput:\n\t\t%s", type, s);
}
V *jdll;
///
// At runtime, find the libj shared object and populate the function pointers
// to the functions it exposes.
V *loaddl() {
if (!jdll) {
jdll = dlopen(LIBJ, RTLD_LAZY);
JInit = (JIT)dlsym(jdll, "JInit");
JDo = (JDT)dlsym(jdll, "JDo");
JFree = (JFT)dlsym(jdll, "JFree");
JSMX = (JSXT)dlsym(jdll, "JSMX");
JGetM = (JGMT)dlsym(jdll, "JGetM");
JSetM = (JSMT)dlsym(jdll, "JSetM");
JGetA = (JGAT)dlsym(jdll, "JGetA");
JSetA = (JSAT)dlsym(jdll, "JSetA");
}
return jdll;
}
// Initialize a J Engine instance.
J jinit() {
V *j = JInit();
#ifdef JDEBUG
JSMX(j, JOutput, 0, 0, 0, 3);
#endif
return j;
}
// I think this gets the stdout, but I'm honestly not sure.
C *jgetr(J j) { return JGetR(j); }
// Execute a sentence in the given J instance.
int jdo(J j, C *sentence) { return JDo(j, sentence); }
// Get a variable by name from the given J instance.
int jgetm(J j, C *name, I *jt, I *jr, I *js, I *jd) {
return JGetM(j, name, jt, jr, js, jd);
}
// Set a variable by name from the given J instance.
int jsetm(J j, C *name, I *jt, I *jr, I *js, I *jd) {
return JSetM(j, name, jt, jr, js, jd);
}
// Get byte array representation of J object
A jgeta(J j, I n, C *name) { return JGetA(j, n, name); }
// Set J object by byte array
I jseta(J j, I n, C *name, I x, C *data) { return JSetA(j, n, name, x, data); }
// Deinitialize the J instance.
V jfree(J j) { JFree(j); }