Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/facebook/luaffifb.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2015-11-12 23:59:08 +0300
committerSam Gross <colesbury@gmail.com>2015-11-13 00:00:37 +0300
commit9dad64fc2615710fe57d938b890f2f8e50084cbd (patch)
tree65fe99213d9bb2b4d887acddae57074a3290076b
parent077e44036b09fb16a83cbcd5cd53798e1f884063 (diff)
Convert io.* file handles to FILE* pointers.
Fixes #2
-rw-r--r--ffi.c30
-rw-r--r--test.lua13
2 files changed, 35 insertions, 8 deletions
diff --git a/ffi.c b/ffi.c
index 56c1ab8..5890c47 100644
--- a/ffi.c
+++ b/ffi.c
@@ -99,6 +99,24 @@ static int type_error(lua_State* L, int idx, const char* to_type, int to_usr, co
return lua_error(L);
}
+static void* userdata_toptr(lua_State* L, int idx)
+{
+ void* ptr = lua_touserdata(L, idx);
+
+ // check for FILE*
+ lua_getmetatable(L, idx);
+ luaL_getmetatable(L, LUA_FILEHANDLE);
+ int isfile = lua_rawequal(L, -1, -2);
+ lua_pop(L, 2);
+
+ if (isfile) {
+ luaL_Stream* stream = (luaL_Stream*) ptr;
+ return stream->f;
+ }
+
+ return ptr;
+}
+
static int cdata_tointeger(lua_State* L, int idx, ptrdiff_t* val)
{
struct ctype ct;
@@ -213,7 +231,7 @@ static int get_cfunction_address(lua_State* L, int idx, cfunction* addr);
if (!ALLOW_POINTERS) { \
type_error(L, idx, #TYPE, 0, NULL); \
} \
- ret = (TYPE) (intptr_t) p; \
+ ret = (TYPE) (intptr_t) userdata_toptr(L, idx); \
} else if (ct.pointers || ct.type == STRUCT_TYPE || ct.type == UNION_TYPE) {\
if (!ALLOW_POINTERS) { \
type_error(L, idx, #TYPE, 0, NULL); \
@@ -346,15 +364,13 @@ static size_t unpack_vararg(lua_State* L, int i, char* to)
case LUA_TUSERDATA:
p = to_cdata(L, i, &ct);
+ lua_pop(L, 1);
if (ct.type == INVALID_TYPE) {
- *(void**) to = p;
+ *(void**) to = userdata_toptr(L, i);
return sizeof(void*);
- }
-
- lua_pop(L, 1);
- if (ct.pointers || ct.type == INTPTR_TYPE) {
+ } else if (ct.pointers || ct.type == INTPTR_TYPE) {
*(void**) to = p;
return sizeof(void*);
@@ -530,7 +546,7 @@ static void* check_pointer(lua_State* L, int idx, struct ctype* ct)
/* some other type of user data */
ct->type = VOID_TYPE;
ct->pointers = 1;
- return lua_touserdata(L, idx);
+ return userdata_toptr(L, idx);
} else if (ct->type == STRUCT_TYPE || ct->type == UNION_TYPE) {
return p;
} else {
diff --git a/test.lua b/test.lua
index 227c3c6..1834ffa 100644
--- a/test.lua
+++ b/test.lua
@@ -768,7 +768,6 @@ check(tostring(ffi.debug().functions.register_foo):match('%b<>'), '<void (*)(int
ffi.cdef [[
typedef struct __sFILE FILE;
- FILE *fopen(const char * , const char * ) __asm("_" "fopen" );
]]
assert(not ffi.istype('int', ffi.new('int*')))
@@ -946,5 +945,17 @@ assert(ffi.string(buf, 0) == '')
assert(ffi.string(buf, ffi.new('long long', 2)) == 'aa')
assert(ffi.string(buf, ffi.new('int', 2)) == 'aa')
+-- Test io.tmpfile()
+ffi.cdef [[
+ int fprintf ( FILE * stream, const char * format, ... );
+]]
+local f = io.tmpfile()
+ffi.C.fprintf(f, "test: %s\n", "foo")
+
+f:seek("set", 0)
+local str = f:read('*l')
+assert(str == 'test: foo', str)
+f:close()
+
print('Test PASSED')