lua与C++粘合层框架

一.   lua调用C++

      在lua中是以函数指针的形式调用函数, 并且所有的函数指针都必须满足如下此种类型:
typedef int (*lua_CFunction) (lua_State *L);  
也就是说, 偶们在C++中定义函数时必须以lua_State为参数, 以int为返回值才能被Lua所调用. 但是不要忘记了, 偶们的lua_State是支持栈的, 所以通过栈可以传递无穷个参数, 大小只受内存大小限制. 而返回的int值也只是指返回值的个数真正的返回值都存储在
lua_State的栈中. 偶们通常的做法是做一个wrapper, 把所有需要调用的函数都wrap一下, 这样就可以调用任意的函数了.

#include<iostream>
using namespace std;
#include<stdio.h>
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
//#pragma comment(lib, "lua5.1.lib")
lua_State* L;
static int average(lua_State *L)
{//返回栈中元素的个数int n = lua_gettop(L);double sum = 0;int i;for (i = 1; i <= n; i++){if (!lua_isnumber(L, i)) {lua_pushstring(L, "Incorrect argument to 'average'");lua_error(L);}sum += lua_tonumber(L, i);}/* push the average */lua_pushnumber(L, sum / n);/* push the sum */lua_pushnumber(L, sum);/* return the number of results */return 2;
}
int main (int argc,char*argv[])
{/* initialize Lua */L = lua_open();/* load Lua libraries */luaL_openlibs(L);/* register our function */lua_register(L, "average", average);/* run the script */luaL_dofile(L, "e15.lua");lua_getglobal(L,"avg");cout<<"avg is:"<<lua_tointeger(L,-1)<<endl;lua_pop(L,1);lua_getglobal(L,"sum");cout<<"sum is:"<<lua_tointeger(L,-1)<<endl;/* cleanup Lua */lua_close(L);return 0;
}
//程序
//*lua_gettop()的作用是返回栈顶元素的序号. 由于Lua的栈是从1开始编号的,
// 所以栈顶元素的序号也相当于栈中的元素个数. 在这里, 栈中元素的个数就
// 是传入的参数个数.
//* for循环计算所有传入参数的总和. 这里用到了数值转换lua_tonumber().
//* 然后偶们用lua_pushnumber()把平均值和总和push到栈中.
//* 最后, 偶们返回2, 表示有两个返回值.
//* 虽然在C++中定义了average()函数, 但Lua程序并不知道, 所以需
//  要在main函数中加入
//     // register our function 
//  lua_register(L, "average", average);
//  这两行的作用就是告诉e15.lua有average()这样一个函数.
//* 这个程序可以存成cpp也可以存成c, 如果以.c为扩展名就不需要加extern "C"
//     
//编译的方法偶们上次说过了, 方法相同.
//e15.lua执行的方法只能用上例中的C++中执行, 而不能用命令行方式执行.*/


目标:

  1. 独立,无需第三方库依赖
  2. 小巧,仅提供大多数场景的功能需求
  3. 易用,接口简单明确
  4. 方便,提供完备的错误信息

 

目录结构:

image

state.hpp—对lua_state封装,支持对内存定制

reference.hpp—对lua的function、string、table引用,提高性能会用到

module.hpp--支持类似C++中namespace功能,以table方式实现

lua_reg.hpp--头文件包含

iterator.hpp--对不定参数的迭代

execute.hpp--执行lua文件,对lua_pcall封装,支持错误处理

error.hpp--错误处理,提供fatal_error与parameter_error,支持对堆栈内容的解析

converter.hpp--C++数据与lua数据的转换,默认支持C++原生类型、std::string\std::pair\std::tuple\std::map\std::vector

config.hpp--这个没什么好说的

class.hpp--对C++类的支持

call.hpp--lua_pcall封装,C++调用lua函数,支持错误处理


优势:

1. 可定制内存分配器,满足allocate、deallocate即可,默认使用std::allocator

2. 错误信息丰富,堆栈、参数列表、详情

3. 参数转换可扩展,采用模板偏特化方式实现,默认有std::vector\std::pair\std::tuple\std::map\std::string等STL容器类型

4. 支持lua中namespace(即module),采用table实现



实现机制:

 1. lua参数与C++参数转换

<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1: </span><span class="kwrd">template</span> < <span class="kwrd">typename</span> T, <span class="kwrd">typename</span> EnableT = <span class="kwrd">void</span> ></span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum2" class="lnum">   2:</span> <span class="kwrd">struct</span> convertion_t;</span>

当需要对lua与C++参数进行转换时,请考虑片特化此类,如void*对应lightuserdata

<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1:</span> <span class="kwrd">template</span> < ></span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum2" class="lnum">   2:</span> <span class="kwrd">struct</span> convertion_t<<span class="kwrd">void</span> *></span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum3" class="lnum">   3:</span> {</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum4" class="lnum">   4:</span>     <span class="kwrd">static</span> <span class="kwrd">void</span> * from(state_t &state, <span class="kwrd">int</span> index)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum5" class="lnum">   5:</span>     {</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum6" class="lnum">   6:</span>         LUAREG_ERROR(lua_islightuserdata(state, index) != 0, LUA_TLIGHTUSERDATA, index);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum7" class="lnum">   7:</span>  </span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum8" class="lnum">   8:</span>         <span class="kwrd">return</span> ::lua_touserdata(state, index);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum9" class="lnum">   9:</span>     }</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum10" class="lnum">  10:</span>  </span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum11" class="lnum">  11:</span>     <span class="kwrd">static</span> std::uint32_t to(state_t &state, <span class="kwrd">void</span> *val)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum12" class="lnum">  12:</span>     {</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum13" class="lnum">  13:</span>         <span class="kwrd">if</span>( val != nullptr )</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum14" class="lnum">  14:</span>             ::lua_pushlightuserdata(state, val);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum15" class="lnum">  15:</span>         <span class="kwrd">else</span></span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum16" class="lnum">  16:</span>             ::lua_pushnil(state);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum17" class="lnum">  17:</span>  </span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum18" class="lnum">  18:</span>         <span class="kwrd">return</span> 1;</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum19" class="lnum">  19:</span>     }</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum20" class="lnum">  20:</span> };</span>

2. C++函数与lua函数对应关系

当需要把C++函数注册到lua,如

<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1:</span> <span class="kwrd">int</span> test2(<span class="kwrd">int</span> n, <span class="kwrd">double</span> d, <span class="kwrd">const</span> std::string &msg)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum2" class="lnum">   2:</span> {</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum3" class="lnum">   3:</span>     <span class="kwrd">return</span> 10;</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum4" class="lnum">   4:</span> }</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1:</span> luareg::module(state, <span class="str">"cpp"</span>)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum2" class="lnum">   2:</span>         << lua::def(<span class="str">"test2"</span>, &test2);</span>

在lua::def函数里,首先会推导test2的函数签名

<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1:</span> <span class="kwrd">template</span> < <span class="kwrd">typename</span> R, <span class="kwrd">typename</span> ...Args ></span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum2" class="lnum">   2:</span> <span class="kwrd">inline</span> details::free_function_t<R, Args...> def(<span class="kwrd">const</span> <span class="kwrd">char</span> *name, R(*func)(Args...))</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum3" class="lnum">   3:</span> {</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum4" class="lnum">   4:</span>     <span class="kwrd">return</span> details::free_function_t<R, Args...>(name, func);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum5" class="lnum">   5:</span> }</span>
根据模版参数,得到返回值类型,参数类型,构建一个free_function_t对象
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1:</span> <span class="kwrd">template</span> < <span class="kwrd">typename</span> R, <span class="kwrd">typename</span> ...Args ></span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum2" class="lnum">   2:</span> <span class="kwrd">struct</span> free_function_t</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum3" class="lnum">   3:</span> {</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum4" class="lnum">   4:</span>     <span class="kwrd">const</span> <span class="kwrd">char</span> *name_;</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum5" class="lnum">   5:</span>  </span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum6" class="lnum">   6:</span>     <span class="kwrd">typedef</span> R(*function_t)(Args...);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum7" class="lnum">   7:</span>     function_t function_;</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum8" class="lnum">   8:</span>  </span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum9" class="lnum">   9:</span>     free_function_t(<span class="kwrd">const</span> <span class="kwrd">char</span> *name, function_t func)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum10" class="lnum">  10:</span>         : name_(name)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum11" class="lnum">  11:</span>         , function_(func)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum12" class="lnum">  12:</span>     {}</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum13" class="lnum">  13:</span> };</span>
free_function_t对象保存注册名及当前函数指针,通过operator<<操作符把这个free_function_t匿名对象给module的临时匿名对象
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1:</span> <span class="kwrd">inline</span> module_t module(state_t &state, <span class="kwrd">const</span> <span class="kwrd">char</span> *name = nullptr)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum2" class="lnum">   2:</span> {</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum3" class="lnum">   3:</span>     <span class="kwrd">if</span>( name )</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum4" class="lnum">   4:</span>         assert(std::strlen(name) != 0);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum5" class="lnum">   5:</span>     <span class="kwrd">return</span> module_t(state, name);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum6" class="lnum">   6:</span> }</span>
在module里,提供了operator<<操作符重载
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1:</span> <span class="kwrd">template</span> < <span class="kwrd">typename</span> R, <span class="kwrd">typename</span> ...Args ></span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum2" class="lnum">   2:</span> module_t &<span class="kwrd">operator</span><<(<span class="kwrd">const</span> details::free_function_t<R, Args...> &func)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum3" class="lnum">   3:</span> {</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum4" class="lnum">   4:</span>     <span class="kwrd">auto</span> lambda = [](lua_State *l)-><span class="kwrd">int</span></span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum5" class="lnum">   5:</span>     {</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum6" class="lnum">   6:</span>         state_t state(l);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum7" class="lnum">   7:</span>         <span class="kwrd">typedef</span> <span class="kwrd">typename</span> details::free_function_t<R, Args...>::function_t function_t;</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum8" class="lnum">   8:</span>         <span class="kwrd">auto</span> func = <span class="kwrd">static_cast</span><function_t>(::lua_touserdata(state, lua_upvalueindex(1)));</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum9" class="lnum">   9:</span>         </span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum10" class="lnum">  10:</span>         <span class="kwrd">return</span> details::call(state, func);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum11" class="lnum">  11:</span>     };</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum12" class="lnum">  12:</span>  </span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum13" class="lnum">  13:</span>     ::lua_pushlightuserdata(state_, func.function_);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum14" class="lnum">  14:</span>     ::lua_pushcclosure(state_, lambda, 1);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum15" class="lnum">  15:</span>     ::lua_setfield(state_, -2, func.name_);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum16" class="lnum">  16:</span>  </span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum17" class="lnum">  17:</span>     <span class="kwrd">return</span> *<span class="kwrd">this</span>;</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum18" class="lnum">  18:</span> }</span>

通过把free_function_t对象的function_\name_注册到lua,这里使用了lua_pushccloure这个API,利用upvalue保存了这个注册函数的指针。这里的lambda是Lua_CFunction的原型,一旦lua调用了这个函数,就会回到这个lambda函数体中,再把函数指针取出来进行调用即可。

再来看看这个details::call

<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1:</span> <span class="kwrd">template</span> < <span class="kwrd">typename</span> R, <span class="kwrd">typename</span> ...Args ></span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum2" class="lnum">   2:</span> std::int32_t call(state_t &state, R(*handler)(Args...),</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum3" class="lnum">   3:</span>                   <span class="kwrd">typename</span> std::enable_if<!std::is_same<R, <span class="kwrd">void</span>>::value>::type * = nullptr)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum4" class="lnum">   4:</span> {</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum5" class="lnum">   5:</span>     <span class="kwrd">return</span> convertion_t<R>::to(state, call_impl(state, make_obj(handler), 0));</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum6" class="lnum">   6:</span> }</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1:</span> <span class="kwrd">template</span> < <span class="kwrd">typename</span> R, <span class="kwrd">typename</span> ...Args ></span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum2" class="lnum">   2:</span> std::int32_t call(state_t &state, R(*handler)(Args...),</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum3" class="lnum">   3:</span>                   <span class="kwrd">typename</span> std::enable_if<std::is_same<R, <span class="kwrd">void</span>>::value>::type * = nullptr)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum4" class="lnum">   4:</span> {</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum5" class="lnum">   5:</span>     call_impl(state, make_obj(handler), 0);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum6" class="lnum">   6:</span>  </span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum7" class="lnum">   7:</span>     <span class="kwrd">return</span> 0;</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum8" class="lnum">   8:</span> }</span>

返回值代表返回多少个数据到lua,通过convertion来完成。这里的enable_if来决断调用的C++函数返回值是否为void,如果为void则返回0个参数到lua。

解析就写到这儿吧,至于call_impl和make_obj请大家自己看源码吧,如果有什么不明白的,请加群探讨165666547

 

使用示例:

1. 对lua内存定制,只需要满足allocate、deallocate接口

<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1:</span> std::allocator<<span class="kwrd">char</span>> std_allocator;</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum2" class="lnum">   2:</span> luareg::state_t state(std_allocator);</span>
<span style="font-family: 'Microsoft YaHei UI';"></span> 

2. 注册自由函数

<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1:</span> luareg::module(state, <span class="str">"cpp"</span>)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum2" class="lnum">   2:</span>             << lua::def(<span class="str">"test0"</span>, &test0)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum3" class="lnum">   3:</span>             << lua::def(<span class="str">"test1"</span>, &test1)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum4" class="lnum">   4:</span>             << lua::def(<span class="str">"test2"</span>, &test2)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum5" class="lnum">   5:</span>             << lua::def(<span class="str">"test3"</span>, &test3)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum6" class="lnum">   6:</span>             << lua::def(<span class="str">"test4"</span>, &test4)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum7" class="lnum">   7:</span>             << lua::def(<span class="str">"test5"</span>, &test5)</span>
当然,也可以注册类的成员函数,但是并不是由lua提供的userdata作为对象指针,而是由C++保存的指针
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1:</span> lua::def(<span class="str">"test6"</span>, &t, &test_t::test6);</span>

3. 注册类
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1:</span> luareg::module(state, <span class="str">"cpp"</span>)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum2" class="lnum">   2:</span>             [</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum3" class="lnum">   3:</span>                 luareg::class_t<foo_t>(state, <span class="str">"foo_t"</span>)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum4" class="lnum">   4:</span>                 << luareg::constructor<<span class="kwrd">int</span>>()</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum5" class="lnum">   5:</span>                 << luareg::destructor()</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum6" class="lnum">   6:</span>                 << luareg::def(<span class="str">"add"</span>, &foo_t::add)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum7" class="lnum">   7:</span>                 << luareg::def(<span class="str">"get"</span>, &foo_t::get)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum8" class="lnum">   8:</span>                 << luareg::def(<span class="str">"get_pointer"</span>, &foo_t::get_pointer)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum9" class="lnum">   9:</span>                 << luareg::def(<span class="str">"get_base"</span>, &foo_t::get_base)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum10" class="lnum">  10:</span>             ]</span>
<span style="font-family: 'Microsoft YaHei UI';">需要注意的是constructor与destructor都不是必须的,如果没有,则采用默认。是不是很像luabind的语法呢?</span>
<span style="font-family: 'Microsoft YaHei UI';">4. 执行lua文件</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1:</span> lua::execute(state, <span class="str">"test.lua"</span>);</span>
5. 执行lua的一个函数
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum1" class="lnum">   1:</span> <span class="kwrd">try</span></span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum2" class="lnum">   2:</span>     {</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum3" class="lnum">   3:</span>         lua::execute(state, <span class="str">"test2.lua"</span>);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum4" class="lnum">   4:</span>         std::pair<<span class="kwrd">int</span>, std::string> n = lua::call(state, <span class="str">"test_call"</span>, 1, <span class="str">"haha"</span>, 10.2, false);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum5" class="lnum">   5:</span>  </span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum6" class="lnum">   6:</span>         <span class="kwrd">auto</span> val = std::make_pair(<span class="str">"test abc"</span>, 10.2);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum7" class="lnum">   7:</span>         lua::call(state, <span class="str">"test_call2"</span>, 1, <span class="str">"haha"</span>, val);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum8" class="lnum">   8:</span>     }</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum9" class="lnum">   9:</span>     <span class="kwrd">catch</span>(<span class="kwrd">const</span> luareg::fatal_error_t &e)</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum10" class="lnum">  10:</span>     {</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum11" class="lnum">  11:</span>         std::cout << e.what() << std::endl;</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum12" class="lnum">  12:</span>         e.dump(std::cout);</span>
<span style="font-family: 'Microsoft YaHei UI';"><span id="lnum13" class="lnum">  13:</span>     }</span>
执行lua的test_call函数,返回两个值,因为lua可以返回多值,所以在C++中可以采用tuple或者pair来接收。其中,错误均已throw异常来处理,当然,debug的时候会有assert及堆栈信息和参数信息。
局限性:
  1. 对注册函数均已upvalue的方式来保存,限制了C++导出到lua函数个数(upvalue最大个数为255),不过,我认为这已足够,如果要导出很多接口道lua,那已经是不正常的了
  2. 与luabind比起,某些功能不支持(函数重载、导出变量等)
后记:
本框架大量使用C++11特性,使实现非常优雅的解决许多问题,比如lambda、variadic template、auto、decltype等等,所以,需要理解C++11,如果你有可能,请加入我们的C++11讨论群165666547
github:https://github.com/chenyu2202863/lua_reg


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/444793.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode147 对链表进行插入排序

丢人&#xff0c;我就是按插入排序老老实实写的啊。。。。 别人肯定map了hhh。 对链表进行插入排序。 插入排序的动画演示如上。从第一个元素开始&#xff0c;该链表可以被认为已经部分排序&#xff08;用黑色表示&#xff09;。 每次迭代时&#xff0c;从输入数据中移除一个…

leetcode23 合并K个排序链表

合并 k 个排序链表&#xff0c;返回合并后的排序链表。请分析和描述算法的复杂度。 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1->1->2->3->4->4->5->6 思路&#xff1a;把初始的每一个链表当成数组中的一个数&#xff0c;做…

leetcode237 删除链表中的节点(你意想不到的做法,注意细节)

请编写一个函数&#xff0c;使其可以删除某个链表中给定的&#xff08;非末尾&#xff09;节点&#xff0c;你将只被给定要求被删除的节点。 现有一个链表 -- head [4,5,1,9]&#xff0c;它可以表示为: 示例 1: 输入: head [4,5,1,9], node 5 输出: [4,1,9] 解释: 给定你链…

C++(21)--Astah uml 画C++类图

Astah uml 画C类图1.安装2.使用《老九学堂C课程》《老九学堂C课程》详情请到B站搜索《老九零基础学编程C入门》-------------简单的事情重复做&#xff0c;重复的事情用心做&#xff0c;用心的事情坚持做(老九君)--------------- ASTAH&#xff1a;类图工具&#xff0c;用于理…

redis3.0.0 集群安装详细步骤

Redis集群部署文档(centos6系统) &#xff08;要让集群正常工作至少需要3个主节点&#xff0c;在这里我们要创建6个redis节点&#xff0c;其中三个为主节点&#xff0c;三个为从节点&#xff0c;对应的redis节点的ip和端口对应关系如下&#xff09; 127.0.0.1:7000 127.0.0.1:7…

Redis集群添加节点

Redis集群添加节点 1&#xff1a;首先把需要添加的节点启动 cd /usr/local/cluster/ mkdir 7006 cp /usr/local/cluster/redis.conf /usr/local/cluster/7006/ cd /usr/local/cluster/7006/ vi redis.conf ##修改redis.conf中的port参数的值为7006 redis-server redis.c…

leetcode128 最长连续序列

给定一个未排序的整数数组&#xff0c;找出最长连续序列的长度。 要求算法的时间复杂度为 O(n)。 示例: 输入: [100, 4, 200, 1, 3, 2] 输出: 4 解释: 最长连续序列是 [1, 2, 3, 4]。它的长度为4 思路&#xff1a;map记录某个连续序列端点的最大长度。 对于数字i&#xff…

leetcode102 二叉树的层次遍历

给定一个二叉树&#xff0c;返回其按层次遍历的节点值。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 例如: 给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 返回其层次遍历结果&#xff1a; [ [3], [9,20], [15…

Windows Git客户端搭建

最近开始做Windows 开发&#xff0c;所以找了一些windows下安装git的教程 本文环境&#xff1a; 操作系统&#xff1a;Windows XP SP3 Git客户端&#xff1a;TortoiseGit-1.8.16.0-32bit 一、安装Git客户端 全部安装均采用默认&#xff01; 1. 安装支撑软件 msysgit: http://ms…

C++(23)--多态性与虚函数

多态性与虚函数1.静态多态-重载2.动态多态-重写2.1 向上转换/向下转换3.虚函数的工作原理4.纯虚函数和抽象类5.补充项目(都市浮生记)-卒《老九学堂C课程》学习笔记。《老九学堂C课程》详情请到B站搜索《老九零基础学编程C入门》-------------简单的事情重复做&#xff0c;重复的…

如何在Appscale下发布自己的应用(一)

本篇文章主要讲如何在本地搭建appscale环境。由于国内的信息资源有限&#xff0c;很多重要的论坛被墙了&#xff0c;所以遇到不少麻烦&#xff0c;由于最近一段时间vpn也被封掉了&#xff0c;我只能通过特殊渠道方法来翻墙查阅资料&#xff0c;走了不少弯路。 1.先说系统和环境…

如何在Appscale下发布自己的应用(二)

本文开始讲如何发布自己的app应用到appscle上 建好appscle网站后&#xff0c;可以在命令行通过 appscle deploy apppathname 来发布自己应用。 除了用命令行提交应用之外&#xff0c;还可以通过appscale的网站直接提交&#xff0c;选择 upload application->选择上传文件-&g…

Xcode的Architectures和Valid Architectures的区别

目录[-] Xcode的Architectures和Valid Architectures的区别 Architectures Valid Architectures 原因解释如下&#xff1a; 参考1&#xff1a; 所有IOS设备详情列表 List of iOS devices - Wikipedia, the free encyclopedia 参考2&#xff1a; iOS 7: 如何为iPhone 5S编译64位…

leetcode887 鸡蛋掉落

你将获得 K 个鸡蛋&#xff0c;并可以使用一栋从 1 到 N 共有 N 层楼的建筑。 每个蛋的功能都是一样的&#xff0c;如果一个蛋碎了&#xff0c;你就不能再把它掉下去。 你知道存在楼层 F &#xff0c;满足 0 < F < N 任何从高于 F 的楼层落下的鸡蛋都会碎&#xff0c;…

PaperNotes(15)-图神经网络、PyG极简版入门笔记

图神经网络概况1.GNN,GCN,GE的区别2.图卷积的通式--矩阵该如何作用2.1实现12.2实现22.3实现33.PyTorch geometric3.1 PyG内置数据集3.1.1ENZYMES dataset3.1.2Cora3.2 PyG自定义数据集3.2.1Data构建简单的图结构3.2.2 Dataset3.2.3 InMemoryDataset一文读懂图卷积GCN(https://z…

leetcode76 最小覆盖子串

给你一个字符串 S、一个字符串 T&#xff0c;请在字符串 S 里面找出&#xff1a;包含 T 所有字母的最小子串。 示例&#xff1a; 输入: S "ADOBECODEBANC", T "ABC" 输出: "BANC" 说明&#xff1a; 如果 S 中不存这样的子串&#xff0c;则返…

Servlet 工程 web.xml 中的 servlet 和 servlet-mapping 标签

摘录某个工程的 web.xml 文件片段&#xff1a;访问顺序为1—>2—>3—>4&#xff0c;其中2和3的值必须相同。 url-pattern 标签中的值是要在浏览器地址栏中输入的 url&#xff0c;可以自己命名&#xff0c;这个 url 访问名为 servlet-name 中值的 servlet&#xff0c;两…

leetcode236 二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也可以是它自己的…

leetcode279 完全平方数

给定正整数 n&#xff0c;找到若干个完全平方数&#xff08;比如 1, 4, 9, 16, ...&#xff09;使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。 示例 1: 输入: n 12 输出: 3 解释: 12 4 4 4. 示例 2: 输入: n 13 输出: 2 解释: 13 4 9. 思路&#xf…

leetcode240. 搜索二维矩阵 II

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 示例: 现有矩阵 matrix 如下&#xff1a; [ [1, 4, 7, 11, 15], [2, 5, 8, 12, 19], [3, 6…