diff --git a/daemon/ffimodule.c b/daemon/ffimodule.c index 31a1560f48beb4b5e98733c651cb326208a71162..1cb6b715c2ee887400fe73c1a3b6c13e81b91901 100644 --- a/daemon/ffimodule.c +++ b/daemon/ffimodule.c @@ -38,7 +38,7 @@ enum { SLOT_produce, SLOT_checkout, SLOT_answer_finalize, - SLOT_count + SLOT_count /* dummy, must be the last */ }; #define SLOT_size sizeof(int) @@ -107,13 +107,6 @@ static int l_ffi_init(struct kr_module *module) return l_ffi_call(L, 1); } -/** @internal Unregister layer callback reference from registry. */ -#define LAYER_UNREGISTER(L, api, name) do { \ - int *cb_slot = (int *)((char *)api + sizeof(kr_layer_api_t)); \ - if (cb_slot[SLOT_ ## name] > 0) \ - luaL_unref(L, LUA_REGISTRYINDEX, cb_slot[SLOT_ ## name]); \ -} while(0) - static int l_ffi_deinit(struct kr_module *module) { /* Deinit the module in Lua (if possible) */ @@ -122,32 +115,31 @@ static int l_ffi_deinit(struct kr_module *module) if (l_ffi_preface(module, "deinit")) { ret = l_ffi_call(L, 1); } + module->lib = NULL; /* Free the layer API wrapper (unconst it) */ kr_layer_api_t* api = module->data; - if (api) { - LAYER_UNREGISTER(L, api, begin); - LAYER_UNREGISTER(L, api, finish); - LAYER_UNREGISTER(L, api, consume); - LAYER_UNREGISTER(L, api, produce); - LAYER_UNREGISTER(L, api, checkout); - LAYER_UNREGISTER(L, api, answer_finalize); - LAYER_UNREGISTER(L, api, reset); - free(api); + if (!api) { + return ret; } - module->lib = NULL; + /* Unregister layer callback references from registry. */ + for (int si = 0; si < SLOT_count; ++si) { + if (api->cb_slots[si] > 0) { + luaL_unref(L, LUA_REGISTRYINDEX, api->cb_slots[si]); + } + } + free(api); return ret; } -#undef LAYER_UNREGISTER /** @internal Helper for retrieving layer Lua function by name. */ -#define LAYER_FFI_CALL(ctx, slot) \ - int *cb_slot = (int *)((char *)(ctx)->api + sizeof(kr_layer_api_t)); \ - if (cb_slot[SLOT_ ## slot] <= 0) { \ +#define LAYER_FFI_CALL(ctx, slot_name) \ + const int *cb_slot = (ctx)->api->cb_slots + SLOT_ ## slot_name; \ + if (*cb_slot <= 0) { \ return ctx->state; \ } \ struct kr_module *module = (ctx)->api->data; \ lua_State *L = module->lib; \ - lua_rawgeti(L, LUA_REGISTRYINDEX, cb_slot[SLOT_ ## slot]); \ + lua_rawgeti(L, LUA_REGISTRYINDEX, *cb_slot); \ lua_pushnumber(L, ctx->state) static int l_ffi_layer_begin(kr_layer_t *ctx) @@ -219,11 +211,11 @@ static int l_ffi_layer_answer_finalize(kr_layer_t *ctx) /** @internal Conditionally register layer trampoline * @warning Expects 'module.layer' to be on top of Lua stack. */ #define LAYER_REGISTER(L, api, name) do { \ - int *cb_slot = (int *)((char *)api + sizeof(kr_layer_api_t)); \ + int *cb_slot = (api)->cb_slots + SLOT_ ## name; \ lua_getfield((L), -1, #name); \ if (!lua_isnil((L), -1)) { \ (api)->name = l_ffi_layer_ ## name; \ - cb_slot[SLOT_ ## name] = luaL_ref((L), LUA_REGISTRYINDEX); \ + *cb_slot = luaL_ref((L), LUA_REGISTRYINDEX); \ } else { \ lua_pop((L), 1); \ } \ @@ -234,7 +226,8 @@ static kr_layer_api_t *l_ffi_layer_create(lua_State *L, struct kr_module *module { /* Fabricate layer API wrapping the Lua functions * reserve slots after it for references to Lua callbacks. */ - const size_t api_length = sizeof(kr_layer_api_t) + (SLOT_count * SLOT_size); + const size_t api_length = offsetof(kr_layer_api_t, cb_slots) + + (SLOT_count * SLOT_size); kr_layer_api_t *api = malloc(api_length); if (api) { memset(api, 0, api_length); diff --git a/lib/layer.h b/lib/layer.h index dc69cfcb38a7a7036fda55ac301a9492c8c87687..c3db71c51a18fe91e5e86ef65f3c5ad54c076a59 100644 --- a/lib/layer.h +++ b/lib/layer.h @@ -90,6 +90,9 @@ struct kr_layer_api { /** The module can store anything in here. */ void *data; + + /** Internal to ./daemon/ffimodule.c. */ + int cb_slots[]; }; typedef struct kr_layer_api kr_layer_api_t;