mirror of
https://github.com/lxsang/antd-lua-plugin
synced 2024-12-28 02:18:21 +01:00
working ffi
This commit is contained in:
parent
9c1837d939
commit
0ac77828e7
2
lib.mk
2
lib.mk
@ -2,7 +2,7 @@ include ../../var.mk
|
|||||||
main:$(LIB_OBJ) $(LIB_NAME)
|
main:$(LIB_OBJ) $(LIB_NAME)
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(LIB_CFLAGS) $(LIB_INC) -fPIC $(LUA_H) -I$(REAL_PLUGINS_BASE) -c $< -o $@
|
$(CC) $(LIB_CFLAGS) -D DEBUG $(LIB_INC) -fPIC $(LUA_H) -I$(REAL_PLUGINS_BASE) -c $< -o $@
|
||||||
|
|
||||||
%.$(LIB_EXT): %.o
|
%.$(LIB_EXT): %.o
|
||||||
-mkdir $(LIB_BUILD_DIR)
|
-mkdir $(LIB_BUILD_DIR)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
local path = "/home/blackjack/workspace/ant-http/plugins/antd-lua-plugin/lib/ffi/example/libtest.so"
|
||||||
require("cif")
|
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 lib = nil
|
||||||
local fn = nil
|
local fn = nil
|
||||||
local rettype = nil
|
local rettype = nil
|
||||||
@ -7,38 +7,54 @@ local argtype = nil
|
|||||||
lib = FFI.load(path)
|
lib = FFI.load(path)
|
||||||
if lib then
|
if lib then
|
||||||
-- now try to lookup for the greet function
|
-- now try to lookup for the greet function
|
||||||
echo("looking for greet")
|
|
||||||
fn = FFI.lookup(lib,"greet")
|
fn = FFI.lookup(lib,"greet")
|
||||||
if fn then
|
if fn then
|
||||||
-- now the function found
|
-- now the function
|
||||||
-- tried to called it
|
-- tried to called it
|
||||||
rettype = FFI.atomic(FFI.type.VOID) -- void
|
rettype = FFI.atomic(FFI.type.UINT8) -- voidn
|
||||||
if rettype then
|
|
||||||
argtype = {
|
argtype = {
|
||||||
FFI.atomic(FFI.type.POINTER),
|
FFI.atomic(FFI.type.POINTER),
|
||||||
FFI.atomic(FFI.type.DOUBLE),
|
FFI.atomic(FFI.type.DOUBLE),
|
||||||
FFI.atomic(FFI.type.SINT64),
|
FFI.atomic(FFI.type.SINT64),
|
||||||
FFI.atomic(FFI.type.SINT8)
|
FFI.atomic(FFI.type.SINT8)
|
||||||
} -- pointer
|
} -- pointer
|
||||||
if(argtype) then
|
|
||||||
-- call the function
|
-- call the function
|
||||||
local r = FFI.call(rettype, argtype, fn, {"hello world", 0.987, -76, 65})
|
local r = FFI.call(rettype, argtype, fn, {"hello world", 0.987, -76, 65})
|
||||||
if r then
|
if r then
|
||||||
echo("BIG SUCCESS")
|
echo(r)
|
||||||
else
|
else
|
||||||
echo("HELL FAIL")
|
echo("HELL FAIL")
|
||||||
end
|
end
|
||||||
else
|
|
||||||
echo("argtype not found")
|
|
||||||
end
|
end
|
||||||
else
|
fn = FFI.lookup(lib, "test_struct")
|
||||||
echo("return type not found")
|
if fn then
|
||||||
|
local struct1 = FFI.struct({
|
||||||
|
FFI.atomic(FFI.type.UINT8), -- char
|
||||||
|
FFI.atomic(FFI.type.SINT32), -- char
|
||||||
|
FFI.atomic(FFI.type.SINT16), -- char
|
||||||
|
FFI.atomic(FFI.type.UINT8), -- char
|
||||||
|
})
|
||||||
|
local struct = FFI.struct({
|
||||||
|
FFI.atomic(FFI.type.UINT8), -- char
|
||||||
|
struct1,
|
||||||
|
FFI.atomic(FFI.type.SINT32), -- int
|
||||||
|
FFI.atomic(FFI.type.UINT8), -- char
|
||||||
|
})
|
||||||
|
rettype = struct --FFI.atomic(FFI.type.DOUBLE)
|
||||||
|
echo("call with struct")
|
||||||
|
local r = FFI.call(rettype,{struct},fn,{{65, {66, 2048, -97,67},-1024, 68}})
|
||||||
|
if r then echo(JSON.encode(r)) end
|
||||||
|
--echo(JSON.encode(FFI.meta(struct1)))
|
||||||
end
|
end
|
||||||
else
|
|
||||||
echo("unable to find greet")
|
fn = FFI.lookup(lib, "test_string")
|
||||||
|
if(fn) then
|
||||||
|
local buff = FFI.new(256)
|
||||||
|
FFI.call(FFI.atomic(FFI.type.VOID),{FFI.atomic(FFI.type.POINTER), FFI.atomic(FFI.type.POINTER)}, fn, {buff,"Hello world"})
|
||||||
|
echo(FFI.string(buff))
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
FFI.unloadAll()
|
FFI.unloadAll()
|
||||||
else
|
|
||||||
echo("unable to load the lib")
|
|
||||||
end
|
end
|
||||||
echo("end the day")
|
echo("end the day")
|
@ -1,6 +1,34 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
void greet(const char* msg, float num, int sint, char c)
|
|
||||||
|
typedef struct{
|
||||||
|
char a;
|
||||||
|
int b;
|
||||||
|
short c;
|
||||||
|
char d;
|
||||||
|
} inner_t;
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
char a;
|
||||||
|
inner_t b;
|
||||||
|
int c;
|
||||||
|
char d;
|
||||||
|
} test_t;
|
||||||
|
|
||||||
|
char greet(const char* msg, float num, int sint, char c)
|
||||||
{
|
{
|
||||||
printf("%s: '%f' '%d' '%c'\n", msg, num, sint, c);
|
printf("%s: '%f' '%d' '%c'\n", msg, num, sint, c);
|
||||||
|
return 'A';
|
||||||
|
}
|
||||||
|
|
||||||
|
test_t test_struct(test_t data)
|
||||||
|
{
|
||||||
|
printf("data is '%c' '%c' '%d' '%d' '%c' '%d' '%c'\n", data.a, data.b.a, data.b.b, data.b.c, data.b.d, data.c, data.d);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_string(char* buff, const char* a)
|
||||||
|
{
|
||||||
|
sprintf(buff,"you say %s", a);
|
||||||
|
printf("%s\n", buff);
|
||||||
}
|
}
|
331
lib/ffi/ffi.c
331
lib/ffi/ffi.c
@ -22,11 +22,6 @@
|
|||||||
|
|
||||||
#define MAX_FN_ARGC 32
|
#define MAX_FN_ARGC 32
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t allocated;
|
|
||||||
uint8_t is_pointer;
|
|
||||||
void* data;
|
|
||||||
} arg_pointer_t;
|
|
||||||
// define atomic type
|
// define atomic type
|
||||||
typedef enum ffi_atomic_t {
|
typedef enum ffi_atomic_t {
|
||||||
L_FFI_TYPE_VOID,
|
L_FFI_TYPE_VOID,
|
||||||
@ -146,84 +141,102 @@ static int l_ffi_prepare(lua_State* L, ffi_type** argvtype, int idx)
|
|||||||
return argc;
|
return argc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void parser_value(lua_State* L, int idx, ffi_type* ffitype, arg_pointer_t * ptr)
|
void parser_value(lua_State* L, int idx, ffi_type* ffitype, void * data)
|
||||||
{
|
{
|
||||||
ptr->allocated = 1;
|
intptr_t address = (intptr_t) data;
|
||||||
ptr->is_pointer = 0;
|
int offset = 0;
|
||||||
|
int pad = 0;
|
||||||
|
int i = 0;
|
||||||
switch(ffitype->type)
|
switch(ffitype->type)
|
||||||
{
|
{
|
||||||
case FFI_TYPE_POINTER:
|
case FFI_TYPE_POINTER:
|
||||||
ptr->allocated = 0;
|
if(lua_isstring(L,idx))
|
||||||
ptr->is_pointer = 1;
|
*((void**)data) = (void*)lua_tostring(L, idx);
|
||||||
ptr->data = (void*)lua_tostring(L, idx);
|
else
|
||||||
|
*((void**)data) = (void*)lua_touserdata(L, idx);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case FFI_TYPE_UINT8:
|
case FFI_TYPE_UINT8:
|
||||||
ptr->data = (void*) malloc(ffitype->size);
|
*((uint8_t*)data) = (uint8_t)lua_tonumber(L,idx);
|
||||||
*((uint8_t*)ptr->data) = (uint8_t)lua_tonumber(L,idx);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case FFI_TYPE_SINT8:
|
case FFI_TYPE_SINT8:
|
||||||
ptr->data = (void*) malloc(ffitype->size);
|
*((int8_t*)data) = (int8_t)lua_tonumber(L,idx);
|
||||||
*((int8_t*)ptr->data) = (int8_t)lua_tonumber(L,idx);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case FFI_TYPE_UINT16:
|
case FFI_TYPE_UINT16:
|
||||||
ptr->data = (void*) malloc(ffitype->size);
|
*((uint16_t*)data) = (uint16_t)lua_tonumber(L,idx);
|
||||||
*((uint16_t*)ptr->data) = (uint16_t)lua_tonumber(L,idx);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case FFI_TYPE_SINT16:
|
case FFI_TYPE_SINT16:
|
||||||
ptr->data = (void*) malloc(ffitype->size);
|
*((int16_t*)data) = (int16_t)lua_tonumber(L,idx);
|
||||||
*((int16_t*)ptr->data) = (int16_t)lua_tonumber(L,idx);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case FFI_TYPE_UINT32:
|
case FFI_TYPE_UINT32:
|
||||||
ptr->data = (void*) malloc(ffitype->size);
|
*((uint32_t*)data) = (uint32_t)lua_tonumber(L,idx);
|
||||||
*((uint32_t*)ptr->data) = (uint32_t)lua_tonumber(L,idx);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case FFI_TYPE_SINT32:
|
case FFI_TYPE_SINT32:
|
||||||
ptr->data = (void*) malloc(ffitype->size);
|
*((int32_t*)data) = (int32_t)lua_tonumber(L,idx);
|
||||||
*((int32_t*)ptr->data) = (int32_t)lua_tonumber(L,idx);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case FFI_TYPE_UINT64:
|
case FFI_TYPE_UINT64:
|
||||||
ptr->data = (void*) malloc(ffitype->size);
|
*((uint64_t*)data) = (uint64_t)lua_tonumber(L,idx);
|
||||||
*((uint64_t*)ptr->data) = (uint64_t)lua_tonumber(L,idx);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case FFI_TYPE_SINT64:
|
case FFI_TYPE_SINT64:
|
||||||
ptr->data = (void*) malloc(ffitype->size);
|
*((int64_t*)data) = (int64_t)lua_tonumber(L,idx);
|
||||||
*((int64_t*)ptr->data) = (int64_t)lua_tonumber(L,idx);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case FFI_TYPE_LONGDOUBLE:
|
case FFI_TYPE_LONGDOUBLE:
|
||||||
/*This is bug in lua*/
|
/*This is bug in lua*/
|
||||||
ptr->data = (void*) malloc(ffitype->size);
|
*((long double*)data) = (long double)lua_tonumber(L,idx);
|
||||||
*((long double*)ptr->data) = (long double)lua_tonumber(L,idx);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case FFI_TYPE_FLOAT:
|
case FFI_TYPE_FLOAT:
|
||||||
case FFI_TYPE_DOUBLE:
|
case FFI_TYPE_DOUBLE:
|
||||||
ptr->data = (void*) malloc(ffitype->size);
|
*((float*)data) = (float)lua_tonumber(L,idx);
|
||||||
*((float*)ptr->data) = (float)lua_tonumber(L,idx);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
/*case FFI_TYPE_STRUCT:
|
case FFI_TYPE_STRUCT:
|
||||||
// not implemented yet
|
// loop through the table
|
||||||
return NULL;
|
lua_pushvalue(L,idx);
|
||||||
break;*/
|
// stack now contains: -1 => table
|
||||||
default:
|
lua_pushnil(L);
|
||||||
ptr->allocated = 0;
|
// stack now contains: -1 => nil, -2 => table
|
||||||
ptr->is_pointer = 0;
|
while(lua_next(L, -2))
|
||||||
ptr->data = NULL;
|
{
|
||||||
break;
|
// stack now contains: -1 => value; -2 key; -3 table
|
||||||
|
parser_value(L, -1, ffitype->elements[i],data+offset);
|
||||||
|
// pop the value, leaving the original key
|
||||||
|
lua_pop(L,1);
|
||||||
|
// stack now contains: -1 key; -2 table
|
||||||
|
// recalculate offs
|
||||||
|
address += ffitype->elements[i]->size;
|
||||||
|
if(ffitype->elements[i+1])
|
||||||
|
{
|
||||||
|
pad = address % ffitype->elements[i+1]->alignment;
|
||||||
|
if( pad != 0)
|
||||||
|
{
|
||||||
|
pad = ffitype->elements[i+1]->alignment - pad;
|
||||||
|
}
|
||||||
|
|
||||||
|
address += pad;
|
||||||
|
offset += ffitype->elements[i]->size + pad;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
// lua_next return 0, it popout the key at -1, leaving the table
|
||||||
|
// so, popout the table
|
||||||
|
lua_pop(L,1);
|
||||||
|
return;
|
||||||
|
|
||||||
|
default: return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parser_arguments(lua_State* L, int idx, arg_pointer_t* argv, ffi_type** argvtype)
|
static void parser_arguments(lua_State* L, int idx, void** argv, ffi_type** argvtype)
|
||||||
{
|
{
|
||||||
// loop through table
|
// loop through table
|
||||||
lua_pushvalue(L,idx);
|
lua_pushvalue(L,idx);
|
||||||
@ -234,7 +247,8 @@ static void parser_arguments(lua_State* L, int idx, arg_pointer_t* argv, ffi_typ
|
|||||||
while(lua_next(L, -2))
|
while(lua_next(L, -2))
|
||||||
{
|
{
|
||||||
// stack now contains: -1 => value; -2 key; -3 table
|
// stack now contains: -1 => value; -2 key; -3 table
|
||||||
parser_value(L, -1, argvtype[i],&argv[i]);
|
argv[i] = (void*)malloc(argvtype[i]->size);
|
||||||
|
parser_value(L, -1, argvtype[i],argv[i]);
|
||||||
i++;
|
i++;
|
||||||
// pop the value, leaving the original key
|
// pop the value, leaving the original key
|
||||||
lua_pop(L,1);
|
lua_pop(L,1);
|
||||||
@ -245,25 +259,102 @@ static void parser_arguments(lua_State* L, int idx, arg_pointer_t* argv, ffi_typ
|
|||||||
lua_pop(L,1);
|
lua_pop(L,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_arguments(arg_pointer_t* argv, int argc)
|
|
||||||
|
static void ffi_post_call(lua_State* L, void* ret, ffi_type* rettype)
|
||||||
{
|
{
|
||||||
for(int i = 0; i< argc; i++)
|
if(!ret)
|
||||||
{
|
{
|
||||||
if(argv[i].allocated)
|
lua_pushnil(L);
|
||||||
free(argv[i].data);
|
return;
|
||||||
|
}
|
||||||
|
int i = 0;
|
||||||
|
intptr_t address = (intptr_t) ret;
|
||||||
|
int offset = 0;
|
||||||
|
int pad = 0;
|
||||||
|
switch (rettype->type)
|
||||||
|
{
|
||||||
|
case FFI_TYPE_POINTER:
|
||||||
|
lua_pushlightuserdata(L,ret);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FFI_TYPE_UINT8:
|
||||||
|
lua_pushnumber(L, (lua_Number)(*((uint8_t*)ret)));
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_SINT8:
|
||||||
|
lua_pushnumber(L, (lua_Number)(*((int8_t*)ret)));
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_UINT16:
|
||||||
|
lua_pushnumber(L, (lua_Number)(*((uint16_t*)ret)));
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_SINT16:
|
||||||
|
lua_pushnumber(L, (lua_Number)(*((int16_t*)ret)));
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_UINT32:
|
||||||
|
lua_pushnumber(L, (lua_Number)(*((uint32_t*)ret)));
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_SINT32:
|
||||||
|
lua_pushnumber(L, (lua_Number)(*((int32_t*)ret)));
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_UINT64:
|
||||||
|
lua_pushnumber(L, (lua_Number)(*((uint64_t*)ret)));
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_SINT64:
|
||||||
|
lua_pushnumber(L, (lua_Number)(*((int64_t*)ret)));
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_LONGDOUBLE:
|
||||||
|
case FFI_TYPE_FLOAT:
|
||||||
|
case FFI_TYPE_DOUBLE:
|
||||||
|
lua_pushnumber(L, *((double*)ret));
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_STRUCT:
|
||||||
|
lua_newtable(L);
|
||||||
|
for ( i = 0; rettype->elements[i] != NULL; i++)
|
||||||
|
{
|
||||||
|
lua_pushnumber(L,i);
|
||||||
|
ffi_post_call(L, ret + offset,rettype->elements[i]);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
address += rettype->elements[i]->size;
|
||||||
|
if(rettype->elements[i+1])
|
||||||
|
{
|
||||||
|
pad = address % rettype->elements[i+1]->alignment;
|
||||||
|
if( pad != 0)
|
||||||
|
{
|
||||||
|
pad = rettype->elements[i+1]->alignment - pad;
|
||||||
|
}
|
||||||
|
|
||||||
|
address += pad;
|
||||||
|
offset += rettype->elements[i]->size + pad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
lua_pushnil(L);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
static void dump(ffi_type* st)
|
||||||
|
{
|
||||||
|
printf("Type: %d %d\n", st->size, st->alignment);
|
||||||
|
if(st->type == FFI_TYPE_STRUCT)
|
||||||
|
for (int i = 0; st->elements[i] != NULL; i++)
|
||||||
|
{
|
||||||
|
dump(st->elements[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
static int l_ffi_call(lua_State* L)
|
static int l_ffi_call(lua_State* L)
|
||||||
{
|
{
|
||||||
ffi_type * argvtype[MAX_FN_ARGC];
|
ffi_type * argvtype[MAX_FN_ARGC];
|
||||||
void* argv[MAX_FN_ARGC];
|
void* argv[MAX_FN_ARGC];
|
||||||
ffi_type * rettype = lua_touserdata(L,1);
|
ffi_type * rettype = lua_touserdata(L,1);
|
||||||
int argc = l_ffi_prepare(L, argvtype, 2);
|
int argc = l_ffi_prepare(L, argvtype, 2);
|
||||||
arg_pointer_t* args;
|
int len = lua_rawlen(L,4);
|
||||||
ffi_arg ret;
|
void* ret = NULL;
|
||||||
ffi_cif cif;
|
ffi_cif cif;
|
||||||
|
//dump(argvtype[0]);
|
||||||
if(ffi_prep_cif(&cif,FFI_DEFAULT_ABI,argc,rettype,argvtype) == FFI_OK)
|
if(ffi_prep_cif(&cif,FFI_DEFAULT_ABI,argc,rettype,argvtype) == FFI_OK)
|
||||||
{
|
{
|
||||||
void * fn = lua_touserdata(L,3);
|
void * fn = lua_touserdata(L,3);
|
||||||
@ -273,34 +364,28 @@ static int l_ffi_call(lua_State* L)
|
|||||||
lua_pushboolean(L,0);
|
lua_pushboolean(L,0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if(lua_rawlen(L,4) != argc)
|
if(len != argc)
|
||||||
{
|
{
|
||||||
LOG("%s\n", "Argument count does not not match");
|
LOG("Argument count does not not match: expected %d, but have: %d\n", argc, len);
|
||||||
lua_pushboolean(L,0);
|
lua_pushboolean(L,0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
// the arguments of the function is at 4th position on the stack
|
// the arguments of the function is at 4th position on the stack
|
||||||
// we need to loop through this table and check if argument type
|
// we need to loop through this table and check if argument type
|
||||||
// is correct to the definition in argvtype
|
// is correct to the definition in argvtype
|
||||||
args = (arg_pointer_t*)malloc(sizeof(arg_pointer_t)*(argc+1));
|
parser_arguments(L,4,argv,argvtype);
|
||||||
//ret = (void*)malloc(rettype->size);
|
if(rettype->type != FFI_TYPE_VOID)
|
||||||
// now parser the argument
|
ret = (void*)malloc(rettype->size);
|
||||||
parser_arguments(L,4,args,argvtype);
|
ffi_call(&cif,fn, ret, argv);
|
||||||
|
|
||||||
for(int i = 0; i< argc; i++)
|
for(int i = 0; i< argc; i++)
|
||||||
{
|
{
|
||||||
if(args[i].is_pointer && args[i].data)
|
if(argv[i]) free(argv[i]);
|
||||||
argv[i] = &(args[i].data);
|
|
||||||
else
|
|
||||||
argv[i] = args[i].data;
|
|
||||||
}
|
}
|
||||||
ffi_call(&cif,fn, &ret, argv);
|
ffi_post_call(L,ret, rettype);
|
||||||
free_arguments(args, argc);
|
if(ret) free(ret);
|
||||||
if(args) free(args);
|
//lua_pushboolean(L,1);
|
||||||
lua_pushboolean(L,1);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
printf("fail to prepare %d\n");
|
|
||||||
lua_pushboolean(L,0);
|
lua_pushboolean(L,0);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -325,7 +410,9 @@ static int l_ffi_struct(lua_State* L)
|
|||||||
// 1st element in the stack is the
|
// 1st element in the stack is the
|
||||||
// struct table
|
// struct table
|
||||||
int len = lua_rawlen(L,1);
|
int len = lua_rawlen(L,1);
|
||||||
ffi_type* cstruct = lua_newuserdata(L, (len+2) * sizeof(ffi_type) );
|
ffi_type* cstruct = lua_newuserdata(L,sizeof(ffi_type) + (len+1) * sizeof(ffi_type*));
|
||||||
|
void *ptr = (void*)cstruct+(sizeof(ffi_type));
|
||||||
|
cstruct->elements = (ffi_type**)ptr;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
cstruct->size = cstruct->alignment = 0;
|
cstruct->size = cstruct->alignment = 0;
|
||||||
cstruct->type = FFI_TYPE_STRUCT;
|
cstruct->type = FFI_TYPE_STRUCT;
|
||||||
@ -353,6 +440,112 @@ static int l_ffi_struct(lua_State* L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int l_ffi_new(lua_State* L)
|
||||||
|
{
|
||||||
|
int size = luaL_checkinteger(L, 1);
|
||||||
|
void* ptr = lua_newuserdata(L, size);
|
||||||
|
memset(ptr,size,0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_ffi_meta(lua_State* L)
|
||||||
|
{
|
||||||
|
ffi_type* type = lua_touserdata(L,1);
|
||||||
|
if(type)
|
||||||
|
{
|
||||||
|
lua_newtable(L);
|
||||||
|
lua_pushstring(L,"size");
|
||||||
|
lua_pushnumber(L, type->size);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
|
||||||
|
lua_pushstring(L,"alignment");
|
||||||
|
lua_pushnumber(L, type->alignment);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
|
||||||
|
lua_pushstring(L,"type");
|
||||||
|
switch (type->type)
|
||||||
|
{
|
||||||
|
case FFI_TYPE_POINTER:
|
||||||
|
lua_pushstring(L, "POINTER");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FFI_TYPE_UINT8:
|
||||||
|
lua_pushstring(L, "UINT8");
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_SINT8:
|
||||||
|
lua_pushstring(L, "SINT8");
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_UINT16:
|
||||||
|
lua_pushstring(L, "UINT16");
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_SINT16:
|
||||||
|
lua_pushstring(L, "SINT16");
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_UINT32:
|
||||||
|
lua_pushstring(L, "UINT32");
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_SINT32:
|
||||||
|
lua_pushstring(L, "SINT32");
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_UINT64:
|
||||||
|
lua_pushstring(L, "UINT64");
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_SINT64:
|
||||||
|
lua_pushstring(L, "SINT64");
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_LONGDOUBLE:
|
||||||
|
lua_pushstring(L, "LONGDOUBLE");
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_FLOAT:
|
||||||
|
lua_pushstring(L, "FLOAT");
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_DOUBLE:
|
||||||
|
lua_pushstring(L, "DOUBLE");
|
||||||
|
break;
|
||||||
|
case FFI_TYPE_STRUCT:
|
||||||
|
lua_pushstring(L, "STRUCT");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
lua_pushnil(L);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_settable(L, -3);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
lua_pushnil(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_ffi_offset(lua_State* L)
|
||||||
|
{
|
||||||
|
void* ptr = lua_touserdata(L, 1);
|
||||||
|
int off = luaL_checkinteger(L,2);
|
||||||
|
if(ptr)
|
||||||
|
{
|
||||||
|
lua_pushlightuserdata(L, ptr + off);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
lua_pushnil(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static int l_ffi_string(lua_State* L)
|
||||||
|
{
|
||||||
|
void* ptr = lua_touserdata(L,1);
|
||||||
|
if(ptr)
|
||||||
|
lua_pushstring(L, (const char*)ptr);
|
||||||
|
else
|
||||||
|
lua_pushstring(L, "");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static int l_ffi_free(lua_State* L)
|
||||||
|
{
|
||||||
|
void* ptr = lua_touserdata(L,1);
|
||||||
|
if(ptr)
|
||||||
|
free(ptr);
|
||||||
|
lua_pushboolean(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
static const struct luaL_Reg _lib [] = {
|
static const struct luaL_Reg _lib [] = {
|
||||||
{"dlopen", l_dlopen},
|
{"dlopen", l_dlopen},
|
||||||
{"dlsym",l_dlsym},
|
{"dlsym",l_dlsym},
|
||||||
@ -360,6 +553,12 @@ static const struct luaL_Reg _lib [] = {
|
|||||||
{"call",l_ffi_call},
|
{"call",l_ffi_call},
|
||||||
{"atomic", l_ffi_atomic_type},
|
{"atomic", l_ffi_atomic_type},
|
||||||
{"struct", l_ffi_struct },
|
{"struct", l_ffi_struct },
|
||||||
|
{"new", l_ffi_new},
|
||||||
|
{"meta", l_ffi_meta},
|
||||||
|
{"at", l_ffi_offset},
|
||||||
|
// special case: pointer to string
|
||||||
|
{"string", l_ffi_string},
|
||||||
|
{"free", l_ffi_free},
|
||||||
{NULL,NULL}
|
{NULL,NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user