diff options
author | Sam Gross <colesbury@gmail.com> | 2015-11-12 23:59:08 +0300 |
---|---|---|
committer | Sam Gross <colesbury@gmail.com> | 2015-11-13 00:00:37 +0300 |
commit | 9dad64fc2615710fe57d938b890f2f8e50084cbd (patch) | |
tree | 65fe99213d9bb2b4d887acddae57074a3290076b | |
parent | 077e44036b09fb16a83cbcd5cd53798e1f884063 (diff) |
Convert io.* file handles to FILE* pointers.
Fixes #2
-rw-r--r-- | ffi.c | 30 | ||||
-rw-r--r-- | test.lua | 13 |
2 files changed, 35 insertions, 8 deletions
@@ -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 { @@ -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') |