From f87456341f533df05eb2deace46075ab00f020da Mon Sep 17 00:00:00 2001 From: lxsang Date: Wed, 1 May 2019 22:06:48 +0200 Subject: [PATCH] working simple ffi --- lib/ffi/example/example.lua | 59 ++++++++-------- lib/ffi/example/lib.c | 4 +- lib/ffi/ffi.c | 137 +++++++++++++++++++++++------------- 3 files changed, 118 insertions(+), 82 deletions(-) diff --git a/lib/ffi/example/example.lua b/lib/ffi/example/example.lua index a29d967..34dcaa7 100644 --- a/lib/ffi/example/example.lua +++ b/lib/ffi/example/example.lua @@ -1,45 +1,44 @@ -local ffi = require("ffi") -local path = "/home/mrsang/Desktop/testffi/libtest.so" +require("cif") +local path = "/Users/mrsang/Google Drive/ushare/cwp/ant-http/plugins/antd-lua-plugin/lib/ffi/example/libtest.so" local lib = nil local fn = nil local rettype = nil local argtype = nil -if ffi then - -- now ffi exist - -- try to load the test library - lib = ffi.dlopen(path) - if lib then - -- now try to lookup for the greet function - echo("looking for greet") - fn = ffi.dlsym(lib,"greet") - if fn then - -- now the function found - -- tried to called it - rettype = ffi.atomic_type(0) -- void - if rettype then - argtype = ffi.atomic_type(20) -- pointer - if(argtype) then - -- call the function - local r = ffi.call(rettype, {argtype}, fn, {"hello world"}) - if r then - echo("BIG SUCCESS") - else - echo("HELL FAIL") - end +lib = FFI.load(path) +if lib then + -- now try to lookup for the greet function + echo("looking for greet") + fn = FFI.lookup(lib,"greet") + if fn then + -- now the function found + -- tried to called it + rettype = FFI.atomic(FFI.type.VOID) -- void + if rettype then + argtype = { + FFI.atomic(FFI.type.POINTER), + FFI.atomic(FFI.type.DOUBLE), + FFI.atomic(FFI.type.SINT64), + FFI.atomic(FFI.type.SINT8) + } -- pointer + if(argtype) then + -- call the function + local r = FFI.call(rettype, argtype, fn, {"hello world", 0.987, -76, 65}) + if r then + echo("BIG SUCCESS") else - echo("argtype not found") + echo("HELL FAIL") end else - echo("return type not found") + echo("argtype not found") end else - echo("unable to find greet") + echo("return type not found") end - ffi.dlclose(lib) else - echo("unable to load the lib") + echo("unable to find greet") end + FFI.unloadAll() else - echo("cannot find ffi") + echo("unable to load the lib") end echo("end the day") \ No newline at end of file diff --git a/lib/ffi/example/lib.c b/lib/ffi/example/lib.c index e0bbf25..e801162 100644 --- a/lib/ffi/example/lib.c +++ b/lib/ffi/example/lib.c @@ -1,6 +1,6 @@ #include -void greet(const char* msg) +void greet(const char* msg, float num, int sint, char c) { - printf("%s\n", msg); + printf("%s: '%f' '%d' '%c'\n", msg, num, sint, c); } diff --git a/lib/ffi/ffi.c b/lib/ffi/ffi.c index df0febe..b8d5f74 100644 --- a/lib/ffi/ffi.c +++ b/lib/ffi/ffi.c @@ -21,6 +21,12 @@ #include #define MAX_FN_ARGC 32 + +typedef struct { + uint8_t allocated; + uint8_t is_pointer; + void* data; +} arg_pointer_t; // define atomic type typedef enum ffi_atomic_t { L_FFI_TYPE_VOID, @@ -88,15 +94,12 @@ static int l_dlopen(lua_State* L) static int l_dlclose(lua_State* L) { - LOG("%s\n","Begin close"); void* handle = lua_touserdata(L,1); if(!handle) { - LOG("%s\n","Cannot close that thing, handle not found"); lua_pushboolean(L,0); return 1; } - LOG("%s\n","the handle is found"); dlclose(handle); lua_pushboolean(L,1); return 1; @@ -143,42 +146,84 @@ static int l_ffi_prepare(lua_State* L, ffi_type** argvtype, int idx) return argc; } -void * parser_value(lua_State* L, int idx, ffi_type* ffitype) +void parser_value(lua_State* L, int idx, ffi_type* ffitype, arg_pointer_t * ptr) { - lua_Number * value; + ptr->allocated = 1; + ptr->is_pointer = 0; switch(ffitype->type) { - case FFI_TYPE_VOID : return NULL; case FFI_TYPE_POINTER: - // TODO: need to fix this to universal pointer - return lua_tostring(L, idx); + ptr->allocated = 0; + ptr->is_pointer = 1; + ptr->data = (void*)lua_tostring(L, idx); + return; case FFI_TYPE_UINT8: + ptr->data = (void*) malloc(ffitype->size); + *((uint8_t*)ptr->data) = (uint8_t)lua_tonumber(L,idx); + return; + case FFI_TYPE_SINT8: + ptr->data = (void*) malloc(ffitype->size); + *((int8_t*)ptr->data) = (int8_t)lua_tonumber(L,idx); + return; + case FFI_TYPE_UINT16: + ptr->data = (void*) malloc(ffitype->size); + *((uint16_t*)ptr->data) = (uint16_t)lua_tonumber(L,idx); + return; + case FFI_TYPE_SINT16: + ptr->data = (void*) malloc(ffitype->size); + *((int16_t*)ptr->data) = (int16_t)lua_tonumber(L,idx); + return; + case FFI_TYPE_UINT32: + ptr->data = (void*) malloc(ffitype->size); + *((uint32_t*)ptr->data) = (uint32_t)lua_tonumber(L,idx); + return; + case FFI_TYPE_SINT32: + ptr->data = (void*) malloc(ffitype->size); + *((int32_t*)ptr->data) = (int32_t)lua_tonumber(L,idx); + return; + case FFI_TYPE_UINT64: + ptr->data = (void*) malloc(ffitype->size); + *((uint64_t*)ptr->data) = (uint64_t)lua_tonumber(L,idx); + return; + case FFI_TYPE_SINT64: + ptr->data = (void*) malloc(ffitype->size); + *((int64_t*)ptr->data) = (int64_t)lua_tonumber(L,idx); + return; + case FFI_TYPE_LONGDOUBLE: + /*This is bug in lua*/ + ptr->data = (void*) malloc(ffitype->size); + *((long double*)ptr->data) = (long double)lua_tonumber(L,idx); + return; + case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: - value = (lua_Number*) malloc(ffitype->size); - *value = lua_tonumber(L,idx); - break; + ptr->data = (void*) malloc(ffitype->size); + *((float*)ptr->data) = (float)lua_tonumber(L,idx); + return; - case FFI_TYPE_STRUCT: + /*case FFI_TYPE_STRUCT: // not implemented yet return NULL; + break;*/ + default: + ptr->allocated = 0; + ptr->is_pointer = 0; + ptr->data = NULL; break; - default: return NULL; } - return (void*)value; } -static void parser_arguments(lua_State* L, int idx, void** argv, ffi_type** argvtype) +static void parser_arguments(lua_State* L, int idx, arg_pointer_t* argv, ffi_type** argvtype) { // loop through table lua_pushvalue(L,idx); @@ -189,7 +234,7 @@ static void parser_arguments(lua_State* L, int idx, void** argv, ffi_type** argv while(lua_next(L, -2)) { // stack now contains: -1 => value; -2 key; -3 table - argv[i] = parser_value(L, -1, argvtype[i]); + parser_value(L, -1, argvtype[i],&argv[i]); i++; // pop the value, leaving the original key lua_pop(L,1); @@ -200,29 +245,12 @@ static void parser_arguments(lua_State* L, int idx, void** argv, ffi_type** argv lua_pop(L,1); } -static void free_arguments(void** argv, ffi_type** argvtype) +static void free_arguments(arg_pointer_t* argv, int argc) { - ffi_type * ffitype; - for(int i = 0; argvtype[i] != NULL; i++) + for(int i = 0; i< argc; i++) { - ffitype = argvtype[i]; - switch (ffitype->type) - { - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - case FFI_TYPE_LONGDOUBLE: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - if(argv[i]) free(argv[i]); - break; - default: break; - } + if(argv[i].allocated) + free(argv[i].data); } } @@ -230,36 +258,45 @@ static void free_arguments(void** argv, ffi_type** argvtype) static int l_ffi_call(lua_State* L) { ffi_type * argvtype[MAX_FN_ARGC]; + void* argv[MAX_FN_ARGC]; ffi_type * rettype = lua_touserdata(L,1); int argc = l_ffi_prepare(L, argvtype, 2); - printf("Argument count %d\n", argc); - printf("ret type: %d\n", rettype->type); - void* argv[MAX_FN_ARGC]; + arg_pointer_t* args; ffi_arg ret; ffi_cif cif; if(ffi_prep_cif(&cif,FFI_DEFAULT_ABI,argc,rettype,argvtype) == FFI_OK) { - void(* fn)(const char*) = lua_touserdata(L,3); + void * fn = lua_touserdata(L,3); if(!fn) { LOG("%s\n", "function not found"); lua_pushboolean(L,0); return 1; } + if(lua_rawlen(L,4) != argc) + { + LOG("%s\n", "Argument count does not not match"); + lua_pushboolean(L,0); + return 1; + } // the arguments of the function is at 4th position on the stack // we need to loop through this table and check if argument type // is correct to the definition in argvtype - //argv = (void**)malloc(sizeof(void*)*argc); + args = (arg_pointer_t*)malloc(sizeof(arg_pointer_t)*(argc+1)); //ret = (void*)malloc(rettype->size); // now parser the argument - parser_arguments(L,4,argv,argvtype); - // test - char* tmp = (char*)argv[0]; - argv[0] = &tmp; + parser_arguments(L,4,args,argvtype); + + for(int i = 0; i< argc; i++) + { + if(args[i].is_pointer && args[i].data) + argv[i] = &(args[i].data); + else + argv[i] = args[i].data; + } ffi_call(&cif,fn, &ret, argv); - free_arguments(argv, argvtype); - //if(argv) free(argv); - //if(ret) free(ret); + free_arguments(args, argc); + if(args) free(args); lua_pushboolean(L,1); return 1; } @@ -321,7 +358,7 @@ static const struct luaL_Reg _lib [] = { {"dlsym",l_dlsym}, {"dlclose",l_dlclose}, {"call",l_ffi_call}, - {"atomic_type", l_ffi_atomic_type}, + {"atomic", l_ffi_atomic_type}, {"struct", l_ffi_struct }, {NULL,NULL} };