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.pswp.cn/news/444793.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/444793.shtml
英文地址,請注明出處:http://en.pswp.cn/news/444793.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

leetcode147 對鏈表進行插入排序

丟人&#xff0c;我就是按插入排序老老實實寫的啊。。。。 別人肯定map了hhh。 對鏈表進行插入排序。 插入排序的動畫演示如上。從第一個元素開始&#xff0c;該鏈表可以被認為已經部分排序&#xff08;用黑色表示&#xff09;。 每次迭代時&#xff0c;從輸入數據中移除一個…

PaperNotes(13)-Conditional Image Generation with PixelCNN Decoders

conditional Image generation with PixelCNN DecodersICML的best paperpixel cnn 屬于完全可見的信念網絡&#xff0c;需要對 概率密度 建模。給定圖像數據x&#xff0c;想要對概率分布p(x)建模。概率分布p(x)可以看做&#xff0c;每一像素分布同時作用結果的一個聯合分布。一…

Expression : invalid operator 解決方法

從技術上說&#xff0c;用于排序關聯容器的比較函數必須在它們所比較的對象上定義一個“嚴格的弱序化(strict weak ordering)”。&#xff08;傳給sort等算法的比較函數也有同樣的限制&#xff09;,就是兩個對象比大小或先后的規則&#xff0c;比如兩個 string對象比大小的規則…

leetcode23 合并K個排序鏈表

合并 k 個排序鏈表&#xff0c;返回合并后的排序鏈表。請分析和描述算法的復雜度。 示例: 輸入: [ 1->4->5, 1->3->4, 2->6 ] 輸出: 1->1->2->3->4->4->5->6 思路&#xff1a;把初始的每一個鏈表當成數組中的一個數&#xff0c;做…

Xcode LaunchImage 載入界面大小設置

iPhone Portrait iOS 8-Retina HD 5.5 (12422208) @3x iPhone Portrait iOS 8-Retina HD 4.7 (7501334) @2x iPhone Portrait iOS 7,8-2x (640960) @2x iPhone Portrait iOS 7,8-Retina 4 (6401136) @2x iPhone Portrait iOS 5,6-1x (320480) @1x iPhone Portrait iO…

leetcode237 刪除鏈表中的節點(你意想不到的做法,注意細節)

請編寫一個函數&#xff0c;使其可以刪除某個鏈表中給定的&#xff08;非末尾&#xff09;節點&#xff0c;你將只被給定要求被刪除的節點。 現有一個鏈表 -- head [4,5,1,9]&#xff0c;它可以表示為: 示例 1: 輸入: head [4,5,1,9], node 5 輸出: [4,1,9] 解釋: 給定你鏈…

cppcheck值得注意的一些篩選項

使用完cppcheck進行C代碼檢測之后&#xff0c;可能篩選起來很麻煩&#xff0c;一般常見的優化有 emptiness&#xff0c;就是當你使用stl的時候&#xff0c;最好用empty替代size 還有就是 leak

C++(19)--自定義Array,vector練習

自定義Array,vector1.自定義Array2.自定義vector《老九學堂C課程》《C primer》學習筆記。《老九學堂C課程》詳情請到B站搜索《老九零基礎學編程C入門》-------------簡單的事情重復做&#xff0c;重復的事情用心做&#xff0c;用心的事情堅持做(老九君)---------------1.自定義…

讓cocos2dx支持并通過arm64 編譯

為了要支持64位,請把這個文件直接替換到對應的lib目錄下,本來是需要改neton_matrix_impl.c里的宏定義, 在 platform/ios/EAGLVIEW.mm中 在neon_matrix_impl.c中修改 #if defined(__ARM_NEON__) 為#if defined(_ARM_ARCH_7) 還有 third_party目錄下的curl的支持。

springboot——概述

Spring Boot 介紹 Spring Boot 是由 Pivotal 團隊提供的全新框架&#xff0c;其設計?的是?來簡化新 Spring 應? 初始搭建以及開發過 程&#xff0c;該框架使?了特定的?式來進?配置&#xff0c;從?使開發?員不再需要定義樣板化的配置。 默認配置了很多框架的使??式…

C++(20)--類型自動轉換

類型自動轉換1.C內置類型轉換2.實現自定義類的類型轉換《老九學堂C課程》《C primer》學習筆記。《老九學堂C課程》詳情請到B站搜索《老九零基礎學編程C入門》 -------------簡單的事情重復做&#xff0c;重復的事情用心做&#xff0c;用心的事情堅持做(老九君)---------------…

關于遍歷linux的文件目錄的坑- readdir

去年給公司寫了一個配置服務器,目的是解決運維的工作量太大,而且傳送服務器需要的配置文件需要腳本傳送到各個服(每個服ip不一樣,需要scp),然后再刷新通知各個GameServer,中間有沒有傳送失敗并不得知,而且維護相當麻煩,所以我寫了這個服務器,所有區服的配置都在這里邊…

終于,我讀懂了所有Java集合——sort

Collections.sort 事實上Collections.sort方法底層就是調用的Arrays.sort方法&#xff0c;而Arrays.sort使用了兩種排序方法&#xff0c;快速排序和優化的歸并排序。 快速排序主要是對那些基本類型數據&#xff08;int,short,long等&#xff09;排序&#xff0c; 而歸并排序用于…

PRML(1)--緒論(上)多項式曲線擬合、概率論

PRML緒論1.1 多項式曲線擬合1.1.1 問題描述1.1.2 最小化平方和誤差1.1.3 多項式階數確定1.1.4 有趣問題--高階模型為什么效果不好1.1.4 數據集規模對模型的影響1.1.5 參數正則化緩解過擬合問題1.2 概率論1.2.1離散型隨機變量1.2.2 連續型隨機變量1.2.3 期望和方差1.2.4 貝葉斯概…

大數加減乘

如標題&#xff0c;不解釋。 加 #include<stdio.h> #include<string.h> int main() {char a[1000],b[1000];int i,s[1000],len1,len2,len,j;while(scanf("%s%s",a,b)!EOF) //用字符數組來儲存數{for(i0;i<1000;i)s[i]0;len1strlen(a);len2strlen(b…

在GCC和Visual Studio中使用hash_map

熟悉STL或熟悉ACM/ICPC的話&#xff0c;其中的set, map, multiset, multimap一定用過無數次了&#xff0c;它們都是用平衡二叉樹&#xff08;紅黑樹&#xff09;實現的&#xff0c;復雜度為O(lgn)。我們也知道set, map可以通過哈希來實現&#xff0c;復雜度只有O(1)&#xff0c…

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…

PRML(2)--緒論(下)模型選擇、緯度災難、決策論、信息論

PRML緒論1.3 模型選擇1.4 緯度災難1.5 決策論1.5.1最小錯誤分率1.5.2最小化期望損失1.5.3拒絕選項1.5.4推斷和決策1.5.5 回歸問題的損失函數1.6 信息論1.3 模型選擇 模型過復雜會造成過擬合問題&#xff0c;需要通過一些技術來降低模型的復雜度。 就最大似然而言&#xff0c;可…