diff --git a/src/ffi.c b/src/ffi.c index e19b193d..75a49205 100644 --- a/src/ffi.c +++ b/src/ffi.c @@ -558,8 +558,6 @@ static usz ffiTmpAlign(usz n) { return n; } -static B ffiObjs; - static NOINLINE B toW(u8 reT, u8 reW, B x) { switch(reW) { default: UD; case 0: ffi_checkRange(x, 2, "u1", 0, 1); return taga(toBitArr(x)); break; @@ -615,6 +613,7 @@ NOINLINE B readU16Bits(B x) { usz ia=IA(x); u16* xp=tyarr_ptr(x); i32* rp; B r=m NOINLINE B readU32Bits(B x) { usz ia=IA(x); u32* xp=tyarr_ptr(x); f64* rp; B r=m_f64arrv(&rp, ia); for (usz i=0; ia[0].o, GetU(c, i), anyMut, dataStruct + elSz*i); *(void**)ptr = dataStruct; - ffiObjs = vec_addN(ffiObjs, tag(TOBJ(dataAll), OBJ_TAG)); + ffiObjsGlobal = vec_addN(ffiObjsGlobal, tag(TOBJ(dataAll), OBJ_TAG)); } } else if (t->ty==cty_repr) { // any:any B o2 = t->a[0].o; @@ -712,7 +711,7 @@ void genObj(B o, B c, bool anyMut, void* ptr) { cG = taga(cGp); } else cG = toW(reT, reW, c); *(void**)ptr = tyany_ptr(cG); - ffiObjs = vec_addN(ffiObjs, cG); + ffiObjsGlobal = vec_addN(ffiObjsGlobal, cG); } } else if (t->ty==cty_struct || t->ty==cty_starr) { if (!isArr(c)) thrM("FFI: Expected array corresponding to a struct"); @@ -826,8 +825,6 @@ B buildObj(BQNFFIEnt ent, bool anyMut, B* objs, usz* objPos) { } B libffiFn_c2(B t, B w, B x) { - ffiObjs = emptyHVec(); - BoundFn* bf = c(BoundFn,t); B argObj = c(HArr,bf->obj)->a[0]; @@ -859,6 +856,7 @@ B libffiFn_c2(B t, B w, B x) { usz argn = cif->nargs; BQNFFIEnt* ents = c(BQNFFIType,argObj)->a; + ffiObjsGlobal = emptyHVec(); // implicit parameter to genObj for (usz i = 0; i < argn; i++) { BQNFFIEnt e = ents[i+1]; B o; @@ -869,6 +867,7 @@ B libffiFn_c2(B t, B w, B x) { } genObj(e.o, o, e.extra2, tmpAlloc + e.staticOffset); } + B ffiObjs = ffiObjsGlobal; // load the global before ffi_call to prevent issues on recursive calls for (usz i = 0; i < argn; i++) argPtrs[i] = tmpAlloc + ents[i+1].staticOffset; void* res = tmpAlloc + ents[0].staticOffset; @@ -923,7 +922,7 @@ B libffiFn_c2(B t, B w, B x) { assert(objPos == IA(ffiObjs)); } - dec(w); dec(x); dec(ffiObjs); + dec(w); dec(x); decG(ffiObjs); return r; } B libffiFn_c1(B t, B x) { return libffiFn_c2(t, bi_N, x); } diff --git a/test/cases/ffi.bqn b/test/cases/ffi.bqn index 68c4ce3d..0296d63b 100644 --- a/test/cases/ffi.bqn +++ b/test/cases/ffi.bqn @@ -173,8 +173,4 @@ !"FFI: Pointer element type not implemented" % f←@•FFI""‿"bqn_init"‿">**u64" ⋄ F ⟨↕2⟩ # unchecked stuff -# !"FFI: Bad array corresponding to ""i64:c8"": expected 8 elements, got 1" % f←@•FFI""‿"bqn_init"‿">i64:c8" ⋄ F 8⥊2 - -# TODO test somewhere with appropriate signatures -# f←@•FFI"&"‿"foo"‿"{f32,*i8,[5]i8}"‿"*[7]i8"‿"[4]i8"‿"&i8" ⋄ F ⟨⟨1.2, ↕10, ↕5⟩, ⟨↕7, ↕7⟩, ↕4, ⟨123⟩⟩ %% ⟨123⟩ -# f←@•FFI ""‿"foo"‿"{f32,*i8,[5]i8}"‿"*[7]i8"‿"[4]i8"‿"&i8" ⋄ F ⟨⟨1.2, ↕10, ↕5⟩, ⟨↕7, ↕7⟩, ↕4, ⟨123⟩⟩ %% ⟨⟨123⟩⟩ \ No newline at end of file +# !"FFI: Bad array corresponding to ""i64:c8"": expected 8 elements, got 1" % f←@•FFI""‿"bqn_init"‿">i64:c8" ⋄ F 8⥊2 \ No newline at end of file diff --git a/test/ffi/ffiTest.c b/test/ffi/ffiTest.c index 9a2f4df7..8f8d82e0 100644 --- a/test/ffi/ffiTest.c +++ b/test/ffi/ffiTest.c @@ -290,4 +290,33 @@ void arrstruct2Inc(ArrStruct2* b) { b[i].c[1]++; b[i].c[2]++; } +} + +int32_t callWithinMutated(BQNV v, int32_t* data) { + data[3] = 30; + BQNV r = bqn_call1(v, v); + bqn_free(v); + bqn_free(r); + return 123; +} + +typedef struct { + float a0_0; + int8_t* a0_1; + int8_t a0_2[5]; +} ManyArgs0; + +void manyargs(ManyArgs0 a0, int8_t (*a1)[7], int8_t a2[4], int8_t* mut) { + mut++; + *mut++ = (int8_t) a0.a0_0; + *mut++ = a0.a0_1[0]; + *mut++ = a0.a0_1[9]; + *mut++ = a0.a0_2[0]; + *mut++ = a0.a0_2[4]; + *mut++ = a1[0][0]; + *mut++ = a1[0][6]; + *mut++ = a1[1][0]; + *mut++ = a1[1][6]; + *mut++ = a2[0]; + *mut++ = a2[3]; } \ No newline at end of file diff --git a/test/ffi/test.bqn b/test/ffi/test.bqn index a91ec5e0..b45e23f3 100644 --- a/test/ffi/test.bqn +++ b/test/ffi/test.bqn @@ -108,6 +108,22 @@ as2 ← "{[1]i32,[2]"∾as1∾",[3]f64}" f ↩ "lib.so"•FFI ⟨as2, "arrstruct2", as2, "*"∾as2⟩ ⋄ •Out •Repr F ⟨⟨⟨4⟩ ⋄ ⋈∘⋈¨1‿2 ⋄ 1.2‿2.3‿3.4⟩, ⟨⟨⟨5⟩ ⋄ ⋈∘⋈¨10‿20 ⋄ 5.1‿6.1‿7.1⟩⟩⟩ f ↩ "lib.so"•FFI ⟨"&", "arrstruct2Inc", ">&"∾as2⟩ ⋄ •Out •Repr F (⊢⋈50⊸+) ⟨⟨10⟩ ⋄ ⋈∘⋈¨11‿12 ⋄ 13‿14‿15⟩ +f ↩ "lib.so"•FFI "&"‿"manyargs"‿"{f32,*i8,[5]i8}"‿"*[7]i8"‿"[4]i8"‿"&i8" ⋄ •Show F ⟨⟨31, 10+↕10, 5+↕5⟩, ⟨14+↕7, 21+↕7⟩, 40+↕4, 100+↕13⟩ # ⟨100, 31, 10,19, 5,9 ⋄ 14,20, 21,27, 40,43, 112⟩ +f ↩ "lib.so"•FFI ""‿"manyargs"‿"{f32,*i8,[5]i8}"‿"*[7]i8"‿"[4]i8"‿"&i8" ⋄ •Show F ⟨⟨31, 10+↕10, 5+↕5⟩, ⟨14+↕7, 21+↕7⟩, 40+↕4, 100+↕13⟩ + +Section "# nested" +{ + f ← "lib.so"•FFI "i32"‿"callWithinMutated"‿"a"‿"&i32" + g ← @ •FFI "*:i8"‿"memcpy"‿"&i8"‿"*i8"‿"u64" + Fn ← { + ! 𝕩≡fn + •Show 1⊑G ⟨5⥊0, 3+↕5, 4⟩ + "hello" + } + •Show F ⟨fn, ↕10⟩ +} + + # erroring: # "lib.so" •FFI ""‿"printArgs"‿"i8"‿"i16:c32"‿"i32"‿"u8"‿"u16"‿"u32"‿"f32"‿"f64" diff --git a/test/ffi/test.expected b/test/ffi/test.expected index 69ccdafe..abae41e1 100644 --- a/test/ffi/test.expected +++ b/test/ffi/test.expected @@ -127,3 +127,9 @@ text 30 ⟨⟨9⟩,⟨⟨⟨21⟩⟩,⟨⟨12⟩⟩⟩,1‿2‿17.799999999999997⟩ ⟨⟨⟨11⟩,⟨⟨⟨11⟩⟩,⟨⟨13⟩⟩⟩,13‿15‿16⟩,⟨⟨61⟩,⟨⟨⟨61⟩⟩,⟨⟨63⟩⟩⟩,63‿65‿66⟩⟩ +⟨ 100 31 10 19 5 9 14 20 21 27 40 43 112 ⟩ +⟨ ⟨ 100 31 10 19 5 9 14 20 21 27 40 43 112 ⟩ ⟩ + +# nested +⟨ 3 4 5 6 0 ⟩ +⟨ 123 ⟨ 0 1 2 30 4 5 6 7 8 9 ⟩ ⟩