From ecfb01a3fefad6fc97695982b659256c91780986 Mon Sep 17 00:00:00 2001 From: Josh Nussbaum Date: Mon, 21 Sep 2015 18:50:41 -0400 Subject: [PATCH] Added NIF -> FFI bridge --- Makefile | 18 +++++++ c_src/ffi_nif.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++ c_src/ffi_nif.o | Bin 0 -> 3620 bytes 3 files changed, 154 insertions(+) create mode 100644 Makefile create mode 100644 c_src/ffi_nif.c create mode 100644 c_src/ffi_nif.o diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7af5f62 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +CC=gcc +CFLAGS= +OBJ = ffi_nif.o +TARGET = ffi_nif.so +LIBS += -ldl -lffi +ERTS_INCLUDE_PATH=/home/josh/Playground/erlangs/erts-6.0/include +DIR=c_src + +$(DIR)/%.o: $(DIR)/%.c $(DEPS) + $(CC) -c -o $@ $< $(CFLAGS) -I$(ERTS_INCLUDE_PATH) + +$(TARGET): $(DIR)/$(OBJ) + $(CC) -shared -o $@ $^ $(CFLAGS) $(LIBS) + +.PHONY : $(TARGET) + +clean : + $(RM) $(DIR)/*.o *.so diff --git a/c_src/ffi_nif.c b/c_src/ffi_nif.c new file mode 100644 index 0000000..9bdbb18 --- /dev/null +++ b/c_src/ffi_nif.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include + +#define MAXLEN 1024 + +enum { + VOID = 0, + STRING, + INT +} TYPE; + +static void call(int argc, ffi_type **args, void **values, ffi_type* returnType) { + ffi_cif cif; + int returnValue; + + if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, argc, returnType, args) == FFI_OK) { + ffi_call(&cif, (void*)puts, &returnValue, values); + } +} + +static ERL_NIF_TERM nif_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + char library[MAXLEN], + function[MAXLEN]; + + int argumentsLength, valuesLength, returnType, returnValue, i; + + ErlNifCharEncoding encoding = ERL_NIF_LATIN1; + + if (!enif_get_atom(env, argv[0], library, MAXLEN, encoding)) { + return enif_make_badarg(env); + } + + if (!enif_get_atom(env, argv[1], function, MAXLEN, encoding)) { + return enif_make_badarg(env); + } + + if (!enif_get_list_length(env, argv[2], &argumentsLength)) { + return enif_make_badarg(env); + } + + if (!enif_get_int(env, argv[3], &returnType)) { + return enif_make_badarg(env); + } + + if (!enif_get_list_length(env, argv[4], &valuesLength)) { + return enif_make_badarg(env); + } + + if (valuesLength != argumentsLength) { + return enif_make_badarg(env); + } + + ffi_type *ffiArgs[argumentsLength], *ffiReturnType = &ffi_type_sint; + int args[argumentsLength]; + void *ffiValues[valuesLength]; + ERL_NIF_TERM head, tail = argv[2]; + uint type; + + for (i=0;enif_get_list_cell(env, tail, &head, &tail);i++) { + ffi_type *ffiType; + + enif_get_uint(env, head, &type); + + args[i] = type; + + switch (type) { + case VOID: + ffiType = &ffi_type_void; + break; + case STRING: + ffiType = &ffi_type_pointer; + break; + case INT: + ffiType = &ffi_type_sint; + break; + } + + ffiArgs[i] = ffiType; + } + + tail = argv[4]; + + int intData; + char charData[MAXLEN]; + char *s = charData; + + for (i=0;enif_get_list_cell(env, tail, &head, &tail);i++) { + type = args[i]; + + switch (type) { + case VOID: + break; + case STRING: + enif_get_string(env, head, charData, MAXLEN, encoding); + + ffiValues[i] = &s; + + break; + case INT: + enif_get_int(env, head, &intData); + + ffiValues[i] = &intData; + + break; + } + } + + switch (returnType) { + case VOID: + ffiReturnType = &ffi_type_void; + break; + case STRING: + ffiReturnType = &ffi_type_pointer; + break; + case INT: + ffiReturnType = &ffi_type_sint; + break; + } + + printf("%s.%s() %d %d\n", library, function, argumentsLength, returnType); + + call(argumentsLength, ffiArgs, ffiValues, ffiReturnType); + + returnValue = 100; + + return enif_make_int(env, returnValue); +} + +static ErlNifFunc nif_funcs[] = { + {"nif_call", 5, nif_call} +}; + +ERL_NIF_INIT(Elixir.FFI, nif_funcs, NULL, NULL, NULL, NULL) diff --git a/c_src/ffi_nif.o b/c_src/ffi_nif.o new file mode 100644 index 0000000000000000000000000000000000000000..8c1655a9c284eb9eac66c88fb97c4d1036633ee0 GIT binary patch literal 3620 zcmbtWZD?Cn7(O>iZQQc9`>31S)ZkKRm1UcqgAIk&HQj_V%3OxiZ6Qr>+R!8|$?e!g za4uf)dWr5&Kyadh$bL-lheC0pt=-m5`lFyfL!jGLRqEK9|*%aYQ}%+^e%E1F($v z4gI4(=I6~wgQ0%_Lj7r`i4tam6avDB6iQ`FBBwHC zJXcPu7fY^x2Nx??Vbr%oyjyaHJBwFv#q*oU=Iq^M6LEP5=>6&4c-OkT8|Z!RZoIE} zu@ch7)S2|oZ?x*g`j{qCS?r!SN&Iq%W79rEzY6(;K8Y{wTv4YXy633Z;B4xwTV^=(e`3wbSUiSi8xH0O zhzb2NzD)S~+cN9Vz!pni;_Dpl#plb^rEbjBWo9M18-df7xG<+^>+s3d7Un$K`Wu@j z^eH?1jkPX%d4+~27tWM{%p%PZt{~G=OqpY`#7yOtD>1#>C#H|q>rdmF+83z}7mjX4 zz5F*^^b4R}#eOY|t(0K;P8+haN+GLJNd2j|V8~*+uj>ozbK5)0S?qRDy<&3RWr4*a z^FV<&cA2`h)T2vQWa@55X$ME;UKeMDTpZp%Zc`(R+K8TpJ(`3J#R=}w0*yU#=+kDA zZl=8YvIQDlA*%oDB! zhTD7-n5KNVDc{@@Z0f~tnaHM+u|zzb7Lj!7cq$j}?0i=AsPRnrSUj6br{hBG*}Z#L zusPZ@oYjW6bfvQK++c8fct^N(^R{6re6q#jg5(&AeoJjaS&ww z?R9?L^UR7G&;E-r5zUZ4W$T7mq@zz2e6M@G?KR`=m)c=?5h}*%$G8N$Wxxxzowh+Z ze+fiT1;XvlTowKX9qPkyk}o@b6$%l z1}uBEKbFkJGb$&&Gk64M+zajtfp7N|>$3r`gMvs}`jNs(Qyjcg&7=dK3xl`{-&`zx& z#a{fUN|3O@nU~m^ld7u-auY%TH&L;8#T_$%T+`4sV zt2l6|J0d-Xa_UelkxGi8VJ$Bu(p#lhpQ^>;+F%Bb;4<+6HP#dFjpzC-0oCbL9v?N^ zr}bBaDReVtqn#L1V|j3`PgIn{i?qiEQ@s`2p+P9sT*X+1PpEh*77{{VO=bJU5WZT{ z63fgOHWrhuGnVKdh$Z8xw0vn&*_4L$dJMyZJIZsT;9=_~kA?h-7?*U4c$E-!SW5Ci zV(?wWtA#jf^KTO4(K%!Dmu>xzHvg}UpT}iZ8qt?<)IATNe*r6N@eUK?!8}O}J^yff za9MhAus!RAc$XOQe<6lEfcr$hb;R%s5yNi>F?!Prz#cU7v&49)&J#Z*#JAKVHi35R axe9WU_YeG5^3ZqK`XI0e`ZgP