diff --git a/include/syms b/include/syms deleted file mode 100644 index 27aaacdc..00000000 --- a/include/syms +++ /dev/null @@ -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; -}; \ No newline at end of file diff --git a/makefile b/makefile index 2696874c..00efa0ef 100644 --- a/makefile +++ b/makefile @@ -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) diff --git a/src/ffi.c b/src/ffi.c index 761931f6..08bf4c53 100644 --- a/src/ffi.c +++ b/src/ffi.c @@ -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 -#if FFI==2 -#if !__has_include() -#error " not found. Either install libffi, or add 'FFI=0' as a make argument to disable •FFI" -#endif -#include -#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() + #error " not found. Either install libffi, or add 'FFI=0' as a make argument to disable •FFI" + #endif + #include + #include + #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