赖秀竹 发表于 前天 11:34

自动化 Lua ⟷ C API功能模块(ygluu)

关键词:C/C++、模板、template、反射、Lua、API、绑定、自动化、开发、效率、成本

痛点:

C/C++没有完美的反射功能(如golang/delphi),对开发 Lua ⟷ C API 来说是比较繁琐和耗工时的,并且人工编码的出错率也非常高。
方案

C++模板编译期自动化推导。
优点

•性能高(相比于反射)
•提高开发效率(相比与人工)
•出错率极低(相比与人工)
示例

示例1:注册 C++ 函数到 Lua


示例2:从 C++ 调用 Lua 函数(无函数指针方式)


示例3:从 C++ 调用 Lua 函数(函数指针方式)


代码

/********************************************************************************** **自动化 Lua ⟷ C API功能模块 **author: ygluu **1、Lua->C: 自动推导和注册C-Func参数和返回值给Lua调用 *      函数 alua::reg_lua(L, mod_name, func_name) **2、C->Lua: 自动推导C-Call语句的参数和返回值并调用Lua函数 * *      无返回值调用(常用) *          alua::call_lua(L, mod_name, func_name, lua-args...); **      显式返回类型调用(常用) **          int ret = alua::call_lua(L, mod_name, func_name, lua-args...); **          std::tuple ret = alua::call_lua(L, mod_name, func_name, lua-args...); **          std::map ret = alua::call_lua(L, mod_name, func_name, lua-args...); **      隐式返回类型调用(需声明与LUA函数一致的c-func声明) *          auto ret = alua::call_lua(...); ** 参数和返回值类型支持: *      1、基础类型:int/uint32/int64/uint64/string(const char*)/bool *      2、数组:std::vector *      3、元组:std::tuple *      4、字典:std::map/std::unordered_map ** **********************************************************************************/#pragma once#include "lua.hpp"#include #include #include #include #include #include #include namespace alua{    // 工具:把 __PRETTY_FUNCTION__ 里的裸函数名取出来    namespace    {      // 判断是否是 tuple      template inline constexpr bool is_tuple_v = false;      template inline constexpr bool is_tuple_v = true;      // 计算期望返回数量      template      constexpr int expected_returns() noexcept      {            if constexpr (std::is_same_v) return 0;            else if constexpr (is_tuple_v) return std::tuple_size_v;            else return 1;      }      constexpr std::string_view raw_name(std::string_view pretty) noexcept      {            std::size_t tail = pretty.rfind('(');            if (tail == std::string_view::npos) { return pretty; }            std::size_t head = pretty.rfind(' ', tail);            return (head == std::string_view::npos)                   ? pretty.substr(0, tail)                   : pretty.substr(head + 1, tail - head - 1);      }      // 单值读取 / 压栈      template struct popper;      template struct pusher;      // 数值      template struct popper         { static int         get(lua_State* l,int i){return static_cast(luaL_checkinteger(l,i));}};      template struct popper         { static float         get(lua_State* l,int i){return static_cast(luaL_checknumber(l,i));}};      template struct popper      { static double      get(lua_State* l,int i){return luaL_checknumber(l,i);}};      template struct popper          { static bool          get(lua_State* l,int i){return lua_toboolean(l,i)!=0;}};      template struct popper { static std::uint32_t get(lua_State* l,int i){return static_cast(luaL_checkinteger(l,i));}};      template struct popper { static std::uint64_t get(lua_State* l,int i){return static_cast(luaL_checkinteger(l,i));}};      template struct popper{ static std::int64_tget(lua_State* l,int i){return static_cast(luaL_checkinteger(l,i));}};      // 字符串      template struct popper      {            static std::string get(lua_State* l,int i)            {                std::size_t len = 0;                const char* s = luaL_checklstring(l,i,&len);                return std::string{s,len};            }      };      template struct popper { static const char* get(lua_State* l,int i){return luaL_checkstring(l,i);}};      // 轻量 userdata      template struct popper { static void* get(lua_State* l,int i){return lua_touserdata(l,i);}};      // 压栈      template struct pusher         { static void put(lua_State* l,int v){lua_pushinteger(l,v);}};      template struct pusher         { static void put(lua_State* l,float v){lua_pushnumber(l,v);}};      template struct pusher      { static void put(lua_State* l,double v){lua_pushnumber(l,v);}};      template struct pusher          { static void put(lua_State* l,bool v){lua_pushboolean(l,v);}};      template struct pusher { static void put(lua_State* l,std::uint32_t v){lua_pushnumber(l,v);}};      template struct pusher { static void put(lua_State* l,std::uint64_t v){lua_pushnumber(l,v);}};      template struct pusher{ static void put(lua_State* l,std::int64_t v){lua_pushnumber(l,v);}};      template struct pusher   { static void put(lua_State* l,const std::string& v){lua_pushlstring(l,v.data(),v.size());}};      template struct pusher   { static void put(lua_State* l,const char* v){lua_pushstring(l,v);}};      template struct pusher         { static void put(lua_State* l,void* v){lua_pushlightuserdata(l,v);}};      // vector      template struct popper      {            static std::vector get(lua_State* l,int idx)            {                luaL_checktype(l,idx,LUA_TTABLE);                std::vector v;                lua_pushnil(l);                while(lua_next(l,idx)!=0)                {                  v.emplace_back(popper::get(l,-1));                  lua_pop(l,1);                }                return v;            }      };      template struct pusher      {            static void put(lua_State* l,const std::vector& v)            {                lua_createtable(l,static_cast(v.size()),0);                for(std::size_t i=0;i
页: [1]
查看完整版本: 自动化 Lua ⟷ C API功能模块(ygluu)