Hello ! I have read a post //www.freelists.org/post/luajit/FFI-newby-question-importing-C-functions that describes the same problem I'm trying to solve. Expose host C functions to luajit FFI without make then externally dynamic linkable, on that post it was said that this isn't actually supported by luajit FFI. So I was thing on a workaround and need some feedback from people with more experience with luajit FFI. I'm thinking on creating something like a function pointer in luajit FFI and pass that pointer to the host to set the address of the function then call it from luajit. Bellow is a partial code example showing the idea of how it could be done, any help, comment, suggestion, improvement are welcome. Thanks in advance for your time and attention ! ffi.cdef[[ typedef struct { int (*getStatus)(void *ctx); void (*setStatus)(void *ctx, int status); } host_funcs_t; ]] local host_funcs = ffi.new("host_funcs_t") hostSetHostFuncs(host_funcs) function handleWithContext(ctx) local i = host_funcs.getStatus(ctx) host_funcs.setStatus(ctx, 10) end ------- C side typedef struct { int (*getStatus)(void *ctx); void (*setStatus)(void *ctx, int status); } host_funcs_t; static int lua_hostSetHostFuncs(lua_State *L) { if(!lua_islightuserdata (L, 1) { luaL_error(L, "a lightuserata is expected for this function"); } host_funcs_t *host_funcs = (host_funcs_t*)lua_topointer (L, 1); host_funcs->getStatus = myHostGetStatusFuncAddress; host_funcs->setStatus = myHostSetStatusFuncAddress; return 0; } static int traceback (lua_State *L) { if (!lua_isstring(L, 1)) /* 'message' not a string? */ return 1; /* keep it intact */ lua_getfield(L, LUA_GLOBALSINDEX, "debug"); if (!lua_istable(L, -1)) { lua_pop(L, 1); return 1; } lua_getfield(L, -1, "traceback"); if (!lua_isfunction(L, -1)) { lua_pop(L, 2); return 1; } lua_pushvalue(L, 1); /* pass error message */ lua_pushinteger(L, 2); /* skip this function and traceback */ lua_call(L, 2, 1); /* call debug.traceback */ return 1; } typedef struct { lua_State *L; void *ctx; } my_context_t; static int lua_handle_request(my_context_t *req) { lua_State *L = req->L; int result = 0; if(L) { int saved_top = lua_gettop(L); lua_pushcfunction(L, traceback); /* push traceback function */ int error_func = lua_gettop(L); lua_getglobal(L, "handleWithContext"); if(lua_isfunction(L,-1)) { lua_pushlightuserdata(L,req); if(lua_pcall(L, 1, 1, error_func)) { size_t error_len; const char *error_msg = lua_tolstring(L, -1, &error_len); if(show_errors_on_stdout) printf("%s\n", error_msg); //write_error_message(conn, error_msg, error_len); result = 0; } else { result = lua_toboolean(L, -1) ? 1 : 0; } }; lua_settop(L, saved_top); } return result; }