replace --dynamic-list with visibility

This commit is contained in:
dzaima 2022-11-22 15:36:32 +02:00
parent 6044a0479f
commit 49636bae79
3 changed files with 105 additions and 150 deletions

View File

@ -1,57 +0,0 @@
{
bqn_init;
bqn_free;
bqn_copy;
bqn_toF64;
bqn_toChar;
bqn_readF64;
bqn_readChar;
bqn_type;
bqn_call1;
bqn_call2;
bqn_eval;
bqn_evalCStr;
bqn_bound;
bqn_rank;
bqn_shape;
bqn_pick;
bqn_readI8Arr;
bqn_readI16Arr;
bqn_readI32Arr;
bqn_readF64Arr;
bqn_readC8Arr;
bqn_readC16Arr;
bqn_readC32Arr;
bqn_readObjArr;
bqn_hasField;
bqn_getField;
bqn_makeF64;
bqn_makeChar;
bqn_makeI8Arr;
bqn_makeI16Arr;
bqn_makeI32Arr;
bqn_makeF64Arr;
bqn_makeC8Arr;
bqn_makeC16Arr;
bqn_makeC32Arr;
bqn_makeObjArr;
bqn_makeI8Vec;
bqn_makeI16Vec;
bqn_makeI32Vec;
bqn_makeF64Vec;
bqn_makeC8Vec;
bqn_makeC16Vec;
bqn_makeC32Vec;
bqn_makeObjVec;
bqn_makeUTF8Str;
bqn_makeBoundFn1;
bqn_makeBoundFn2;
bqn_directArrType;
bqn_directI8;
bqn_directI16;
bqn_directI32;
bqn_directF64;
bqn_directC8;
bqn_directC16;
bqn_directC32;
};

View File

@ -44,6 +44,7 @@ c:
i_CC := clang
i_PIE := -no-pie
i_LIBS_LD := -lm
i_LIBS_CC := -fvisibility=hidden
i_FFI := 2
i_singeli := 0
i_OUTPUT := BQN
@ -57,15 +58,6 @@ ifeq ($(i_emcc),1)
else
OUTPUT_BIN := $(OUTPUT)
endif
ifeq ($(i_SHARED),1)
i_PIE := -shared
SHARED_CCFLAGS := -DCBQN_SHARED
ifneq ($(no_fPIC),1)
SHARED_CCFLAGS += -fPIC
endif
else
SHARED_CCFLAGS :=
endif
ifeq ($(origin CC),command line)
i_CC := $(CC)
custom = 1
@ -78,21 +70,26 @@ ifeq ($(origin FFI),command line)
i_FFI := $(FFI)
custom = 1
endif
ifeq ($(i_SHARED),1)
i_PIE := -shared
i_EXPORT := 1
i_LIBS_CC += -DCBQN_SHARED
ifneq ($(no_fPIC),1)
i_LIBS_CC += -fPIC
endif
endif
ifneq ($(i_FFI),0)
i_LIBS_LD += -ldl
ifneq ($(NO_DYNAMIC_LIST),1)
i_LIBS_LD += -Wl,--dynamic-list=include/syms
else
custom = 1
endif
endif
ifeq ($(i_FFI),2)
ifeq ($(shell command -v pkg-config 2>&1 > /dev/null && pkg-config --exists libffi && echo $$?),0)
i_LIBS_LD += $(shell pkg-config --libs libffi)
i_LIBS_CC += $(shell pkg-config --cflags libffi)
else
i_LIBS_LD += -lffi
i_EXPORT := 1
ifeq ($(shell command -v pkg-config 2>&1 > /dev/null && pkg-config --exists libffi && echo $$?),0)
i_LIBS_LD += $(shell pkg-config --libs libffi)
i_LIBS_CC += $(shell pkg-config --cflags libffi)
else
i_LIBS_LD += -lffi -ldl
endif
endif
ifeq ($(i_EXPORT),1)
i_LIBS_LD += -rdynamic
i_LIBS_CC += -DCBQN_EXPORT
endif
ifeq ($(origin LD_LIBS),command line)
i_LIBS_LD := $(LD_LIBS)
@ -139,7 +136,7 @@ else
NOWARN = -Wno-parentheses
endif
ALL_CC_FLAGS = -std=gnu11 -Wall -Wno-unused-function -fms-extensions -ffp-contract=off -fno-math-errno $(CCFLAGS) $(f) $(i_f) $(NOWARN) -DBYTECODE_DIR=$(BYTECODE_DIR) -DSINGELI=$(i_singeli) -DFFI=$(i_FFI) $(SHARED_CCFLAGS) $(i_LIBS_CC)
ALL_CC_FLAGS = -std=gnu11 -Wall -Wno-unused-function -fms-extensions -ffp-contract=off -fno-math-errno $(CCFLAGS) $(f) $(i_f) $(NOWARN) -DBYTECODE_DIR=$(BYTECODE_DIR) -DSINGELI=$(i_singeli) -DFFI=$(i_FFI) $(i_LIBS_CC)
ALL_LD_FLAGS = $(LDFLAGS) $(lf) $(i_lf) $(i_PIE) $(i_LIBS_LD)
ifneq (${manualJobs},1)
@ -191,6 +188,8 @@ ifeq ($(i_singeli), 1)
else
@echo " singeli: not used"
endif
@echo " cc invocation: $(CC_INC) \$$@.d -o \$$@ -c \$$<"
@echo " ld invocation: $(i_LD) ${CCFLAGS} -o [build_dir]/BQN [build_dir]/*.o $(ALL_LD_FLAGS)"
endif
ifeq ($(origin clean),command line)

153
src/ffi.c
View File

@ -1,21 +1,19 @@
#include "core.h"
#if FFI
#include "../include/bqnffi.h"
#include "utils/utf.h"
#include "utils/cstr.h"
#include "nfns.h"
#include "utils/file.h"
#include <dlfcn.h>
#if FFI==2
#if !__has_include(<ffi.h>)
#error "<ffi.h> not found. Either install libffi, or add 'FFI=0' as a make argument to disable •FFI"
#endif
#include <ffi.h>
#include "utils/mut.h"
#include "ns.h"
#if FFI && !defined(CBQN_EXPORT)
#error "Expected CBQN_EXPORT if FFI is defined"
#endif
#if CBQN_EXPORT
#include "../include/bqnffi.h"
#include "utils/utf.h"
#include "utils/cstr.h"
#include "nfns.h"
#include "ns.h"
#include "utils/file.h"
#define EXPORT __attribute__((__visibility__("default")))
// ..continuing under "#if CBQN_EXPORT"
// base interface defs for when GC stuff needs to be added in
static B getB(BQNV v) {
return b(v);
@ -24,10 +22,10 @@ static BQNV makeX(B x) {
return x.u;
}
void bqn_free(BQNV v) {
EXPORT void bqn_free(BQNV v) {
dec(getB(v));
}
BQNV bqn_copy(BQNV v) {
EXPORT BQNV bqn_copy(BQNV v) {
return makeX(inc(getB(v)));
}
@ -35,55 +33,55 @@ static void freeTagged(BQNV v) { }
#define DIRECT_BQNV 1
double bqn_toF64 (BQNV v) { double r = o2fG(getB(v)); freeTagged(v); return r; }
uint32_t bqn_toChar(BQNV v) { uint32_t r = o2cG(getB(v)); freeTagged(v); return r; }
double bqn_readF64 (BQNV v) { return o2fG(getB(v)); }
uint32_t bqn_readChar(BQNV v) { return o2cG(getB(v)); }
EXPORT double bqn_toF64 (BQNV v) { double r = o2fG(getB(v)); freeTagged(v); return r; }
EXPORT uint32_t bqn_toChar(BQNV v) { uint32_t r = o2cG(getB(v)); freeTagged(v); return r; }
EXPORT double bqn_readF64 (BQNV v) { return o2fG(getB(v)); }
EXPORT uint32_t bqn_readChar(BQNV v) { return o2cG(getB(v)); }
void bqn_init() {
EXPORT void bqn_init() {
cbqn_init();
}
B type_c1(B t, B x);
int bqn_type(BQNV v) {
EXPORT int bqn_type(BQNV v) {
return o2i(type_c1(bi_N, inc(getB(v))));
}
BQNV bqn_call1(BQNV f, BQNV x) {
EXPORT BQNV bqn_call1(BQNV f, BQNV x) {
return makeX(c1(getB(f), inc(getB(x))));
}
BQNV bqn_call2(BQNV f, BQNV w, BQNV x) {
EXPORT BQNV bqn_call2(BQNV f, BQNV w, BQNV x) {
return makeX(c2(getB(f), inc(getB(w)), inc(getB(x))));
}
BQNV bqn_eval(BQNV src) {
EXPORT BQNV bqn_eval(BQNV src) {
return makeX(bqn_exec(inc(getB(src)), bi_N, bi_N));
}
BQNV bqn_evalCStr(const char* str) {
EXPORT BQNV bqn_evalCStr(const char* str) {
return makeX(bqn_exec(utf8Decode0(str), bi_N, bi_N));
}
size_t bqn_bound(BQNV a) { return IA(getB(a)); }
size_t bqn_rank(BQNV a) { return RNK(getB(a)); }
void bqn_shape(BQNV a, size_t* buf) { B b = getB(a);
EXPORT size_t bqn_bound(BQNV a) { return IA(getB(a)); }
EXPORT size_t bqn_rank(BQNV a) { return RNK(getB(a)); }
EXPORT void bqn_shape(BQNV a, size_t* buf) { B b = getB(a);
ur r = RNK(b);
usz* sh = SH(b);
for (usz i = 0; i < r; i++) buf[i] = sh[i];
}
BQNV bqn_pick(BQNV a, size_t pos) {
EXPORT BQNV bqn_pick(BQNV a, size_t pos) {
return makeX(IGet(getB(a),pos));
}
// TODO copy directly with some mut.h thing
void bqn_readI8Arr (BQNV a, i8* buf) { B c = toI8Any (incG(getB(a))); memcpy(buf, i8any_ptr (c), IA(c) * 1); dec(c); }
void bqn_readI16Arr(BQNV a, i16* buf) { B c = toI16Any(incG(getB(a))); memcpy(buf, i16any_ptr(c), IA(c) * 2); dec(c); }
void bqn_readI32Arr(BQNV a, i32* buf) { B c = toI32Any(incG(getB(a))); memcpy(buf, i32any_ptr(c), IA(c) * 4); dec(c); }
void bqn_readF64Arr(BQNV a, f64* buf) { B c = toF64Any(incG(getB(a))); memcpy(buf, f64any_ptr(c), IA(c) * 8); dec(c); }
void bqn_readC8Arr (BQNV a, u8* buf) { B c = toC8Any (incG(getB(a))); memcpy(buf, c8any_ptr (c), IA(c) * 1); dec(c); }
void bqn_readC16Arr(BQNV a, u16* buf) { B c = toC16Any(incG(getB(a))); memcpy(buf, c16any_ptr(c), IA(c) * 2); dec(c); }
void bqn_readC32Arr(BQNV a, u32* buf) { B c = toC32Any(incG(getB(a))); memcpy(buf, c32any_ptr(c), IA(c) * 4); dec(c); }
void bqn_readObjArr(BQNV a, BQNV* buf) { B b = getB(a);
EXPORT void bqn_readI8Arr (BQNV a, i8* buf) { B c = toI8Any (incG(getB(a))); memcpy(buf, i8any_ptr (c), IA(c) * 1); dec(c); }
EXPORT void bqn_readI16Arr(BQNV a, i16* buf) { B c = toI16Any(incG(getB(a))); memcpy(buf, i16any_ptr(c), IA(c) * 2); dec(c); }
EXPORT void bqn_readI32Arr(BQNV a, i32* buf) { B c = toI32Any(incG(getB(a))); memcpy(buf, i32any_ptr(c), IA(c) * 4); dec(c); }
EXPORT void bqn_readF64Arr(BQNV a, f64* buf) { B c = toF64Any(incG(getB(a))); memcpy(buf, f64any_ptr(c), IA(c) * 8); dec(c); }
EXPORT void bqn_readC8Arr (BQNV a, u8* buf) { B c = toC8Any (incG(getB(a))); memcpy(buf, c8any_ptr (c), IA(c) * 1); dec(c); }
EXPORT void bqn_readC16Arr(BQNV a, u16* buf) { B c = toC16Any(incG(getB(a))); memcpy(buf, c16any_ptr(c), IA(c) * 2); dec(c); }
EXPORT void bqn_readC32Arr(BQNV a, u32* buf) { B c = toC32Any(incG(getB(a))); memcpy(buf, c32any_ptr(c), IA(c) * 4); dec(c); }
EXPORT void bqn_readObjArr(BQNV a, BQNV* buf) { B b = getB(a);
usz ia = IA(b);
B* p = arr_bptr(b);
if (p!=NULL) {
@ -94,15 +92,15 @@ void bqn_readObjArr(BQNV a, BQNV* buf) { B b = getB(a);
}
}
bool bqn_hasField(BQNV ns, BQNV name) {
EXPORT bool bqn_hasField(BQNV ns, BQNV name) {
return !q_N(ns_getNU(getB(ns), getB(name), false));
}
BQNV bqn_getField(BQNV ns, BQNV name) {
EXPORT BQNV bqn_getField(BQNV ns, BQNV name) {
return makeX(inc(ns_getNU(getB(ns), getB(name), true)));
}
BQNV bqn_makeF64(double d) { return makeX(m_f64(d)); }
BQNV bqn_makeChar(uint32_t c) { return makeX(m_c32(c)); }
EXPORT BQNV bqn_makeF64(double d) { return makeX(m_f64(d)); }
EXPORT BQNV bqn_makeChar(uint32_t c) { return makeX(m_c32(c)); }
static usz calcIA(size_t rank, const size_t* shape) {
@ -125,24 +123,24 @@ static void copyBData(B* r, const BQNV* data, usz ia) {
#define CPYSH(R) usz* sh = arr_shAlloc((Arr*)(R), r0); \
if (sh) PLAINLOOP for (size_t i = 0; RARE(i < r0); i++) sh[i] = sh0[i];
BQNV bqn_makeI8Arr (size_t r0, const size_t* sh0, const i8* data) { usz ia=calcIA(r0,sh0); i8* rp; Arr* r = m_i8arrp (&rp,ia); CPYSH(r); memcpy(rp,data,ia*1); return makeX(taga(r)); }
BQNV bqn_makeI16Arr(size_t r0, const size_t* sh0, const i16* data) { usz ia=calcIA(r0,sh0); i16* rp; Arr* r = m_i16arrp(&rp,ia); CPYSH(r); memcpy(rp,data,ia*2); return makeX(taga(r)); }
BQNV bqn_makeI32Arr(size_t r0, const size_t* sh0, const i32* data) { usz ia=calcIA(r0,sh0); i32* rp; Arr* r = m_i32arrp(&rp,ia); CPYSH(r); memcpy(rp,data,ia*4); return makeX(taga(r)); }
BQNV bqn_makeF64Arr(size_t r0, const size_t* sh0, const f64* data) { usz ia=calcIA(r0,sh0); f64* rp; Arr* r = m_f64arrp(&rp,ia); CPYSH(r); memcpy(rp,data,ia*8); return makeX(taga(r)); }
BQNV bqn_makeC8Arr (size_t r0, const size_t* sh0, const u8* data) { usz ia=calcIA(r0,sh0); u8* rp; Arr* r = m_c8arrp (&rp,ia); CPYSH(r); memcpy(rp,data,ia*1); return makeX(taga(r)); }
BQNV bqn_makeC16Arr(size_t r0, const size_t* sh0, const u16* data) { usz ia=calcIA(r0,sh0); u16* rp; Arr* r = m_c16arrp(&rp,ia); CPYSH(r); memcpy(rp,data,ia*2); return makeX(taga(r)); }
BQNV bqn_makeC32Arr(size_t r0, const size_t* sh0, const u32* data) { usz ia=calcIA(r0,sh0); u32* rp; Arr* r = m_c32arrp(&rp,ia); CPYSH(r); memcpy(rp,data,ia*4); return makeX(taga(r)); }
BQNV bqn_makeObjArr(size_t r0, const size_t* sh0, const BQNV* data) { usz ia=calcIA(r0,sh0); HArr_p r = m_harrUp(ia); CPYSH(r.c); copyBData(r.a,data,ia ); return makeX(r.b); }
EXPORT BQNV bqn_makeI8Arr (size_t r0, const size_t* sh0, const i8* data) { usz ia=calcIA(r0,sh0); i8* rp; Arr* r = m_i8arrp (&rp,ia); CPYSH(r); memcpy(rp,data,ia*1); return makeX(taga(r)); }
EXPORT BQNV bqn_makeI16Arr(size_t r0, const size_t* sh0, const i16* data) { usz ia=calcIA(r0,sh0); i16* rp; Arr* r = m_i16arrp(&rp,ia); CPYSH(r); memcpy(rp,data,ia*2); return makeX(taga(r)); }
EXPORT BQNV bqn_makeI32Arr(size_t r0, const size_t* sh0, const i32* data) { usz ia=calcIA(r0,sh0); i32* rp; Arr* r = m_i32arrp(&rp,ia); CPYSH(r); memcpy(rp,data,ia*4); return makeX(taga(r)); }
EXPORT BQNV bqn_makeF64Arr(size_t r0, const size_t* sh0, const f64* data) { usz ia=calcIA(r0,sh0); f64* rp; Arr* r = m_f64arrp(&rp,ia); CPYSH(r); memcpy(rp,data,ia*8); return makeX(taga(r)); }
EXPORT BQNV bqn_makeC8Arr (size_t r0, const size_t* sh0, const u8* data) { usz ia=calcIA(r0,sh0); u8* rp; Arr* r = m_c8arrp (&rp,ia); CPYSH(r); memcpy(rp,data,ia*1); return makeX(taga(r)); }
EXPORT BQNV bqn_makeC16Arr(size_t r0, const size_t* sh0, const u16* data) { usz ia=calcIA(r0,sh0); u16* rp; Arr* r = m_c16arrp(&rp,ia); CPYSH(r); memcpy(rp,data,ia*2); return makeX(taga(r)); }
EXPORT BQNV bqn_makeC32Arr(size_t r0, const size_t* sh0, const u32* data) { usz ia=calcIA(r0,sh0); u32* rp; Arr* r = m_c32arrp(&rp,ia); CPYSH(r); memcpy(rp,data,ia*4); return makeX(taga(r)); }
EXPORT BQNV bqn_makeObjArr(size_t r0, const size_t* sh0, const BQNV* data) { usz ia=calcIA(r0,sh0); HArr_p r = m_harrUp(ia); CPYSH(r.c); copyBData(r.a,data,ia ); return makeX(r.b); }
BQNV bqn_makeI8Vec (size_t len, const i8* data) { i8* rp; B r = m_i8arrv (&rp,len); memcpy(rp,data,len*1); return makeX(r); }
BQNV bqn_makeI16Vec(size_t len, const i16* data) { i16* rp; B r = m_i16arrv(&rp,len); memcpy(rp,data,len*2); return makeX(r); }
BQNV bqn_makeI32Vec(size_t len, const i32* data) { i32* rp; B r = m_i32arrv(&rp,len); memcpy(rp,data,len*4); return makeX(r); }
BQNV bqn_makeF64Vec(size_t len, const f64* data) { f64* rp; B r = m_f64arrv(&rp,len); memcpy(rp,data,len*8); return makeX(r); }
BQNV bqn_makeC8Vec (size_t len, const u8* data) { u8* rp; B r = m_c8arrv (&rp,len); memcpy(rp,data,len*1); return makeX(r); }
BQNV bqn_makeC16Vec(size_t len, const u16* data) { u16* rp; B r = m_c16arrv(&rp,len); memcpy(rp,data,len*2); return makeX(r); }
BQNV bqn_makeC32Vec(size_t len, const u32* data) { u32* rp; B r = m_c32arrv(&rp,len); memcpy(rp,data,len*4); return makeX(r); }
BQNV bqn_makeObjVec(size_t len, const BQNV* data) { HArr_p r = m_harrUv(len); copyBData(r.a,data,len ); return makeX(r.b); }
BQNV bqn_makeUTF8Str(size_t len, const char* str) { return makeX(utf8Decode(str, len)); }
EXPORT BQNV bqn_makeI8Vec (size_t len, const i8* data) { i8* rp; B r = m_i8arrv (&rp,len); memcpy(rp,data,len*1); return makeX(r); }
EXPORT BQNV bqn_makeI16Vec(size_t len, const i16* data) { i16* rp; B r = m_i16arrv(&rp,len); memcpy(rp,data,len*2); return makeX(r); }
EXPORT BQNV bqn_makeI32Vec(size_t len, const i32* data) { i32* rp; B r = m_i32arrv(&rp,len); memcpy(rp,data,len*4); return makeX(r); }
EXPORT BQNV bqn_makeF64Vec(size_t len, const f64* data) { f64* rp; B r = m_f64arrv(&rp,len); memcpy(rp,data,len*8); return makeX(r); }
EXPORT BQNV bqn_makeC8Vec (size_t len, const u8* data) { u8* rp; B r = m_c8arrv (&rp,len); memcpy(rp,data,len*1); return makeX(r); }
EXPORT BQNV bqn_makeC16Vec(size_t len, const u16* data) { u16* rp; B r = m_c16arrv(&rp,len); memcpy(rp,data,len*2); return makeX(r); }
EXPORT BQNV bqn_makeC32Vec(size_t len, const u32* data) { u32* rp; B r = m_c32arrv(&rp,len); memcpy(rp,data,len*4); return makeX(r); }
EXPORT BQNV bqn_makeObjVec(size_t len, const BQNV* data) { HArr_p r = m_harrUv(len); copyBData(r.a,data,len ); return makeX(r.b); }
EXPORT BQNV bqn_makeUTF8Str(size_t len, const char* str) { return makeX(utf8Decode(str, len)); }
typedef struct BoundFn {
struct NFn;
@ -173,8 +171,8 @@ static B m_ffiFn(NFnDesc* desc, B obj, BB2B c1, BBB2B c2, void* wc1, void* wc2)
r->w_c2 = wc2;
return tag(r, FUN_TAG);
}
BQNV bqn_makeBoundFn1(bqn_boundFn1 f, BQNV obj) { return makeX(m_ffiFn(boundFnDesc, inc(getB(obj)), boundFn_c1, c2_bad, f, NULL)); }
BQNV bqn_makeBoundFn2(bqn_boundFn2 f, BQNV obj) { return makeX(m_ffiFn(boundFnDesc, inc(getB(obj)), c1_bad, boundFn_c2, NULL, f)); }
EXPORT BQNV bqn_makeBoundFn1(bqn_boundFn1 f, BQNV obj) { return makeX(m_ffiFn(boundFnDesc, inc(getB(obj)), boundFn_c1, c2_bad, f, NULL)); }
EXPORT BQNV bqn_makeBoundFn2(bqn_boundFn2 f, BQNV obj) { return makeX(m_ffiFn(boundFnDesc, inc(getB(obj)), c1_bad, boundFn_c2, NULL, f)); }
const static u8 typeMap[] = {
[el_bit] = elt_unk,
@ -184,24 +182,39 @@ const static u8 typeMap[] = {
[el_i32] = elt_i32, [el_c32] = elt_c32,
[el_f64] = elt_f64,
};
BQNElType bqn_directArrType(BQNV a) {
EXPORT BQNElType bqn_directArrType(BQNV a) {
B b = getB(a);
if (!isArr(b)) return elt_unk;
return typeMap[TI(b,elType)];
}
const i8* bqn_directI8 (BQNV a) { return i8any_ptr (getB(a)); }
const i16* bqn_directI16(BQNV a) { return i16any_ptr(getB(a)); }
const i32* bqn_directI32(BQNV a) { return i32any_ptr(getB(a)); }
const f64* bqn_directF64(BQNV a) { return f64any_ptr(getB(a)); }
const u8* bqn_directC8 (BQNV a) { return c8any_ptr (getB(a)); }
const u16* bqn_directC16(BQNV a) { return c16any_ptr(getB(a)); }
const u32* bqn_directC32(BQNV a) { return c32any_ptr(getB(a)); }
EXPORT const i8* bqn_directI8 (BQNV a) { return i8any_ptr (getB(a)); }
EXPORT const i16* bqn_directI16(BQNV a) { return i16any_ptr(getB(a)); }
EXPORT const i32* bqn_directI32(BQNV a) { return i32any_ptr(getB(a)); }
EXPORT const f64* bqn_directF64(BQNV a) { return f64any_ptr(getB(a)); }
EXPORT const u8* bqn_directC8 (BQNV a) { return c8any_ptr (getB(a)); }
EXPORT const u16* bqn_directC16(BQNV a) { return c16any_ptr(getB(a)); }
EXPORT const u32* bqn_directC32(BQNV a) { return c32any_ptr(getB(a)); }
void ffiFn_visit(Value* v) { mm_visit(((BoundFn*)v)->obj); }
DEF_FREE(ffiFn) { dec(((BoundFn*)x)->obj); }
#endif // #if CBQN_EXPORT
#if FFI
#if FFI!=2
#error "Only FFI=0 and FFI=2 are supported"
#endif
#if !__has_include(<ffi.h>)
#error "<ffi.h> not found. Either install libffi, or add 'FFI=0' as a make argument to disable •FFI"
#endif
#include <dlfcn.h>
#include <ffi.h>
#include "utils/mut.h"
// ..continuing under "#if FFI"
typedef struct BQNFFIEnt {
union {
B o; // usual case
@ -910,7 +923,7 @@ void ffi_init() {
TIi(t_ffiType,print) = ffiType_print;
}
#else
#else // i.e. FFI==0
void ffi_init() { }
B ffiload_c2(B t, B w, B x) { thrM("CBQN was compiled without FFI"); }
#endif