##- # Author: Brian Tiffin # Dedicated to the public domain # # Date: Decemeber 2016 # Modified: 2016-12-31/07:10-0500 ##+ # # uniffi.icn, demonstrate an experimental C FFI with libffi # $include "natives.inc" link io procedure main() # will be RTLD_LAZY | RTLD_GLOBAL (so add to the search path) addLibrary := pathload("uniffi.so", "addLibrary") # allow arbitrary C functions, marshalled by libffi native := pathload("uniffi.so", "ffi") # add the testing functions to the dlsym search path, # the handle is somewhat irrelevant, but won't be soonish dlHandle := addLibrary("./testnative.so") write("Unicon dlHandle: ", dlHandle) write() # pass two integers, get the sum as int ans := native("testnative", TYPEINT, 40, 2) write("Unicon: called testnative and got ", ans) if ans ~= 42 then write("ERROR with testnative") write() # pass two reals, get the sum as real ans := native("testdouble", TYPEDOUBLE, 9.0, 8.0) write("Unicon: called testdouble and got ", ans) if ans ~= 17.0 then write("ERROR with testdouble") write() # third arg is an integer, returns real ans := native("testfive", TYPEDOUBLE, 1.0, 2.0, 3, 4.0, 5.0) write("Unicon: called testfive and got ", ans) if ans ~= 15.0 then write("ERROR with testfive") write() # get a pointer/handle ans := native("teststar", TYPESTAR) write("Unicon: called teststar and got ", ans) if ans = 0 then write("ERROR with teststar") write() # a string ans := native("teststring", TYPESTRING, "this is a string") write("Unicon: called teststring and got ", ans) if ans ~== "this is a string" then write("ERROR with teststring") write() # a string, and int and a real, returning string ans := native("testmulti", TYPESTRING, "for multi", 42, &pi) write("Unicon: called testmulti and got ", ans) if ans ~== "for multi" then write("ERROR with testmulti") write() # a string, and int and a real, returning real ans := native("testmultid", TYPEDOUBLE, "for multid", 42, &pi) write("Unicon: called testmultid and got ", ans) if ans ~= &pi then write("ERROR with testmultid") write() # # Variant for float versus double # write("float variant") # pass two reals (as float), get the sum as real (float) ans := native("testfloat", TYPEFLOAT, [9.0, TYPEFLOAT], [8.0, TYPEFLOAT]) write("Unicon: called testfloat and got ", ans) if ans ~= 17.0 then write("ERROR with testfloat") write() # a string, and int and a real (as float), returning real (as float) ans := native("testmultif", TYPEFLOAT, "for multif", 21, [&pi/2, TYPEFLOAT]) write("Unicon: called testmultif and got ", ans) if ans - &pi/2 > 0.0000001 then write("ERROR with testmultif") write() # # standard math lib # # todo: loader needs a path, but pathload stops, need a fail version dlHandle := addLibrary("libm.so") write("Unicon libm dlHandle: ", dlHandle) # call a Bessel function double form ans := native("j0", TYPEDOUBLE, &pi) write("j0(pi) = ", ans) # call Bessel function float form ans := native("j0f", TYPEFLOAT, [&pi, TYPEFLOAT]) write("j0f(pi) = ", ans) write() # test switching back to the previous load library ans := native("testfloat", TYPEFLOAT, [9.0, TYPEFLOAT], [8.0, TYPEFLOAT]) write("Unicon: called testfloat and got: ", ans) if ans ~= 17.0 then write("ERROR with testfloat") write() end