找回密码
 立即注册
首页 业界区 业界 自动化 Lua ⟷ C API功能模块(ygluu)

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

赖秀竹 前天 11:34
关键词:C/C++、模板、template、反射、Lua、API、绑定、自动化、开发、效率、成本

痛点:

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

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

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

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

1.png

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

2.png

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

3.png

代码

[code]/********************************************************************************** *  *  自动化 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_t  get(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
您需要登录后才可以回帖 登录 | 立即注册