From: Josef 'Jeff' Sipek Date: Thu, 25 Feb 2021 15:22:24 +0000 (-0500) Subject: lib-lua: Add DLUA_WRAP_C_DATA macro to more easily expose C structures to lua X-Git-Tag: 2.3.15~172 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=21a2bddaeb9737a91d086c0e24895c70efe19d5c;p=thirdparty%2Fdovecot%2Fcore.git lib-lua: Add DLUA_WRAP_C_DATA macro to more easily expose C structures to lua --- diff --git a/src/lib-lua/Makefile.am b/src/lib-lua/Makefile.am index c2c4e5ac1e..99a64636bc 100644 --- a/src/lib-lua/Makefile.am +++ b/src/lib-lua/Makefile.am @@ -19,7 +19,8 @@ libdovecot_lua_la_LDFLAGS = -export-dynamic headers = \ dlua-compat.h \ dlua-script.h \ - dlua-script-private.h + dlua-script-private.h \ + dlua-wrapper.h pkginc_libdir=$(pkgincludedir) pkginc_lib_HEADERS = $(headers) diff --git a/src/lib-lua/dlua-wrapper.h b/src/lib-lua/dlua-wrapper.h new file mode 100644 index 0000000000..a86c6b255b --- /dev/null +++ b/src/lib-lua/dlua-wrapper.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2020 Josef 'Jeff' Sipek + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef DLUA_WRAPPER_H +#define DLUA_WRAPPER_H + +#define DLUA_WRAP_C_DATA(typename, type, putref, extra_fxns_arg) \ +struct lua_wrapper_##typename { \ + type *ptr; \ + bool ro; \ +}; \ + \ +static inline type *xlua_##typename##_getptr(lua_State *state, int idx, \ + bool *ro_r) \ +{ \ + struct lua_wrapper_##typename *wrapper; \ + \ + wrapper = luaL_checkudata(state, idx, #type); \ + \ + if (ro_r != NULL) \ + *ro_r = wrapper->ro; \ + \ + return wrapper->ptr; \ +} \ + \ +static int xlua_wrapper_##typename##_gc(lua_State *state) \ +{ \ + putref(xlua_##typename##_getptr(state, -1, NULL)); \ + \ + return 0; \ +} \ + \ +static const luaL_Reg provided_##typename##_fxns[] = { \ + { "__gc", xlua_wrapper_##typename##_gc }, \ + { NULL, NULL }, \ +}; \ + \ +/* push [-0,+1,e] */ \ +static void xlua_push##typename(lua_State *state, type *ptr, bool ro) \ +{ \ + struct lua_wrapper_##typename *wrapper; \ + \ + if (ptr == NULL) { \ + lua_pushnil(state); \ + return; \ + } \ + \ + wrapper = lua_newuserdata(state, sizeof(struct lua_wrapper_##typename)); \ + i_assert(wrapper != NULL); \ + \ + wrapper->ptr = (ptr); \ + wrapper->ro = ro; \ + \ + /* get the current metatable */ \ + luaL_getmetatable(state, #type); \ + if (lua_type(state, -1) != LUA_TTABLE) { \ + /* initialize a new metatable */ \ + luaL_Reg *extra_fxns = (extra_fxns_arg); \ + lua_CFunction index; \ + \ + lua_pop(state, 1); \ + luaL_newmetatable(state, #type); \ + luaL_setfuncs(state, provided_##typename##_fxns, 0); \ + \ + index = NULL; \ + if (extra_fxns != NULL) { \ + unsigned i; \ + \ + luaL_setfuncs(state, extra_fxns, 0); \ + \ + for (i = 0; extra_fxns[i].name != NULL; i++) { \ + if (strcmp(extra_fxns[i].name, \ + "__index") == 0) { \ + index = extra_fxns[i].func; \ + break; \ + } \ + } \ + } \ + \ + if (index == NULL) { \ + /* set __index == metatable */ \ + lua_pushliteral(state, "__index"); \ + lua_pushvalue(state, -2); /* dup the table */ \ + lua_settable(state, -3); \ + } \ + } \ + \ + /* set the metatable */ \ + lua_setmetatable(state, -2); \ +} + +#endif