lua是一種目前很流行的高效精簡的指令碼語言。lua乙個特點是比較方便的與c通訊。
然而要在指令碼中使用c++類使用基本的lua方法還是比較麻煩,純手工暴露乙個類的介面到lua工作量還是很大的,而且都是一些簡單的重複勞動。
好在有tolua++這個工具,可以讓程式設計師從簡單的重複勞動解脫出來。
tolua++包含兩個部分,乙個exe,乙個lib,exe用來通過package檔案生成c函式的膠水函式,而lib則用來為生成的膠水函式中用到的輔助函式提供實現。
在lua中要呼叫乙個已有的c函式,大體上可以包含2步:
1、在c程式中實現乙個膠水函式,該函式只有乙個引數lua_state *。在這個膠水函式中,從lua的引數棧中逐個取出引數,再呼叫原有的c函式,最後將c函式的返回結果通過lua的棧傳回給lua環境。
2、將該膠水函式註冊到lua的全域性表中。
雖然這兩個過程都很簡單,但是當要暴露的是c++類大量的成員函式時,為每個函式編寫膠水函式的工作可想而知。
有了tolua++,這個工作就很簡單了,只需要做很少的工作就可以讓tolua++自動為每乙個待暴露的函式實現膠水函式。
如下面這樣乙個c++類,類的實現在乙個命名空間tstns中,類中包含有同一函式名的不同過載及自定義的結構體引數:
#pragma once
#include
using namespace std;
namespace tstns
;class cexport;}
為了使用tolua++匯出這個類到lua中,我們需要寫乙個package檔案,在該檔案中定義**函式需要匯出,我這裡的實現如下:
$#include "export.h"
namespace tstns;
class cexport;}
整 體上export.pkg中的內容基本與export.h檔案類似,需要注意的是第一行:$#include "export.h"。tolua++根據這個檔案來為其中的每個函式生成膠水函式於乙個c檔案中,由於膠水函式需要呼叫原來的函式,所以需要在生成的c 檔案中需要包含export.h這個檔案。第一行就是說在生成的c檔案中插入一行#include 「export.h"
第二個需要注意的地方在於函式的過載,lua並不能根據參考型別自動選擇呼叫哪乙個過載函式,為此我們可以為不同的重載重命名。」@「正是為這一目的設計的。通過重新命名,在lua指令碼中我們就可以顯示的為不同的引數呼叫不同的過載函式。
我們需要使用tolua++的exe來生成膠水函式**。它是乙個命令列程式,可以多個引數:
..\..\tolua++-1.0.93\bin\tolua++ -n export -o ..\lua_export.cpp export.pkg
這一行的意思是說呼叫tolua++.exe根據export.pkg生成乙個..\lua_export.cpp的c++檔案。-n export是說檔案中乙個需要被外面呼叫的c介面為:
int tolua_
export_open (lua_state* tolua_s);
下一步,我們看一下在lua指令碼中如何呼叫我們的匯出的函式。
--file:test.lua
exp=tstns.cexport:new();--首先我例項化乙個cexport的全域性物件。
function foo(a,b)
return exp:foo(a,b);
endfunction strlen(str)
return exp:strlen(str);
endfunction strlen2(str)
return exp:strlen2(str);
endfunction area(rc)
return exp:area(rc);
endfunction area2(prc)
--指標引數使用lua_call.hpp將以void*方式傳入,需要做型別轉換後才能呼叫c++中的**。
return exp:area2(tolua.cast(prc,"tstns::rect"));
endfunction setrect(l,t,r,b)
return exp:setrect(l,t,r,b);
end在這個test.lua中我們實現了幾個函式,在每乙個函式中會呼叫cexport對應的介面。
到此lua呼叫c++的基本框架就已經實現了。
下面再看這個demo如何工作。
找到**中的luatest目錄,並開啟luatest.sln這個vc工程,上面提到的**在工程中都可以找到。
直接編譯可以檢視每乙個函式是如何被呼叫的。
這裡要推薦乙個我改寫的在c++中呼叫lua函式的輔助模板類:lua_call.hpp
採用這個輔助類呼叫lua函式就和呼叫普通的c函式一樣簡單。
下面是luatest.cpp中的**:
// luatest.cpp : 定義控制台應用程式的入口點。 //
#include "stdafx.h"
#include "export.h"
#include "tolua++.h"
extern int tolua_export_open (lua_state* tolua_s);
#include "lua_call.hpp"
//使用模板技術對c++呼叫lua函式進行包裝,使用方法參見_tmain
//對於自定義的資料型別,需要特化push_value,及value_extractor兩個介面。
template<>
void lua_function_base::push_value(tstns::rect rc)
template <>
tstns::rect lua_function_base::value_extractor()
int _tmain(int argc, _tchar* argv) ;
int a1=lua_area(rc);
lua_functionlua_area2(l,"area2");
tstns::rect rc2=;
int a2=lua_area2(&rc2);
lua_functionlua_setarea(l,"setrect");
rc=lua_setarea(5,6,7,8);
lua_functionlus_strlen(l,"strlen");
int nsize1=lus_strlen(std::string("abcdefghij"));
lua_functionlus_strlen2(l,"strlen2");
int nsize2=lus_strlen("abcdefg");
lua_functionfoo(l,"foo");
int sum=foo(5,6); }
lua_close(l);
return 0; }
在_main()中,首先當然是例項化lua環境。
呼叫tolua_export_open(l);註冊tolua++實現的膠水函式到lua。
呼叫lual_dofile(l,"lua/test.lua");執行test.lua指令碼。
呼叫lua指令碼中實現的函式。
最後釋放lua環境:lua_close(l);
這其中lua指令碼中實現的函式是比較取巧的。利用lua_call.hpp,我們只需要兩行**就可以實現:
第一步,定義乙個lua_function物件,找到lua中的函式。
第二步,為函式傳入引數。
需要注意的是,當為cexport新增加乙個需要匯出的函式時,要記得將新的函式名加到export.pkg檔案中,並呼叫tolua++重新生成膠水函式。在demo中有乙個build.bat檔案,每次更新後執行一次即可。
lua呼叫c 的函式 使用tolua
1.定義c 類與函式 include class cppfunctions include cppfunctions.h include include 使用linux下獲取時間的函式 double cppfunctions getcurrenttime 2.繫結 我新建了乙個tolua.h和乙個t...
lua與C(一) C呼叫lua
lua和c有兩種關係 一種是在lua中呼叫c的函式,c稱為庫 一種是c中呼叫lua,c就稱為應用程式 此時c中包含了lua的直譯器 c 部分 注意在c 中,通常要把lua的一些標頭檔案定義在extern c 中,因為他們是c語言實現的。1.作為應用程式呼叫lua char buffer print ...
使用lua實現nginx rewrite
上一次上線只是簡單的把手機端的流量切換手機端的首頁,有點粗糙,現在需要把電腦端相應的頁面切換到電腦端的頁面,直接用nginx自帶的rewrite不太好做,所以用lua做 下面開始 nginx 配置 location mobile.lua 手機訪問重定向到移動版 end其實邏輯也很簡單,主要在ngin...