Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Was too lazy to put this on my github, so here's pastebin
- What is this:
- This calls C functions from lua directly, with no need to make wrapper stubs for every function
- It's designed for Lua 5.2 so don't complain when this isn't working on Lua 5.1
- Usage (I'll use printf in this example):
- lua_State* L = luaL_newstate(L);
- luaL_openlibs(L);
- native::opennative(L);
- native::new_native(L, &printf);
- lua_setglobal(L, "printf");
- And just like that you can call printf from Lua with no need for a wrapper function.
- */
- namespace native
- {
- #ifdef _M_IX86
- typedef std::uint32_t uint_t;
- #else
- typedef std::uint64_t uint_t;
- #endif
- enum class calling_convention
- {
- none_t,
- cdecl_t,
- stdcall_t,
- fastcall_t,
- thiscall_t
- };
- struct native
- {
- calling_convention cc;
- uint_t address;
- native(calling_convention cc, uint_t address) : cc(cc), address(address) {}
- };
- template<std::size_t argc, typename... T>
- uint_t call_t(uint_t func, calling_convention cc, uint_t* args, std::size_t f_argc, T... a)
- {
- if constexpr (argc != 0)
- {
- if (f_argc)
- return call_t<argc - 1>(func, cc, args + 1, f_argc - 1, a..., *args);
- else
- {
- switch (cc)
- {
- case calling_convention::cdecl_t:
- return ((uint_t(__cdecl*)(T...))func)(a...);
- case calling_convention::fastcall_t:
- return ((uint_t(__fastcall*)(T...))func)(a...);
- case calling_convention::stdcall_t:
- return ((uint_t(__stdcall*)(T...))func)(a...);
- case calling_convention::thiscall_t:
- return ((uint_t(__thiscall*)(T...))func)(a...);
- }
- }
- }
- else if (cc == calling_convention::none_t)
- return ((uint_t(*)())func)();
- return 0;
- }
- __forceinline native* luaL_checknative(lua_State* L, int idx)
- {
- return reinterpret_cast<native*>(luaL_checkudata(L, idx, "Native"));
- }
- const void* luaL_topointer(lua_State* L, int idx)
- {
- switch (lua_type(L, idx))
- {
- case LUA_TSTRING:
- return reinterpret_cast<const void*>(lua_tolstring(L, idx, 0));
- case LUA_TLIGHTUSERDATA:
- case LUA_TUSERDATA:
- case LUA_TTABLE:
- case LUA_TFUNCTION:
- case LUA_TTHREAD:
- return lua_topointer(L, idx);
- default: return 0;
- }
- }
- int new_native_decl(lua_State* L)
- {
- native* function = reinterpret_cast<native*>(lua_newuserdata(L, sizeof(native)));
- luaL_getmetatable(L, "Native");
- lua_setmetatable(L, -2);
- return 1;
- }
- int call(lua_State* L)
- {
- native* func = luaL_checknative(L, 1);
- int nargs = lua_gettop(L) - 1;
- uint_t* alloc = nargs ? new uint_t[nargs] : nullptr;
- for (int idx = 0; idx < nargs; idx++)
- alloc[idx] = reinterpret_cast<uint_t>(luaL_topointer(L, idx + 2));
- uint_t ret = call_t<16>(func->address, func->cc, alloc, nargs);
- lua_pushunsigned(L, ret);
- return 1;
- }
- int tostring(lua_State* L)
- {
- native* f = luaL_checknative(L, 1);
- lua_pushfstring(L, "function: %p", f->address);
- return 1;
- }
- const luaL_Reg metamethods[] =
- {
- {"__tostring", tostring},
- {"__call", call}
- };
- void opennative(lua_State* L)
- {
- luaL_newmetatable(L, "Native");
- lua_pushvalue(L, -1);
- lua_setfield(L, -2, "__index");
- luaL_openlib(L, NULL, metamethods, 0);
- }
- void new_native(lua_State* L, void* function, calling_convention cc = calling_convention::cdecl_t)
- {
- new_native_decl(L);
- native* ptr = luaL_checknative(L, -1);
- ptr->address = reinterpret_cast<uint_t>(function);
- ptr->cc = cc;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment