三國殺C/C++ lua tolua++ 編譯 集成,及使用介紹

tolua++ 是用來把 C++代碼 生成 在Lua中使用的接口的工具,編譯步驟比較繁瑣。

使用tolua有以下步驟:

  1. 工程建立
  2. 編寫c/c++文件.
  3. 編寫.pkg文件,填寫需要導出的c/c++接口.
  4. 使用tolua可執行程序將pkg接口導出成LuaVm可調用的棧交互c/c++文件.
  5. 將第三步生成的文件和其他c/c++文件一起編譯生成最終的可執行程序.

1.  工程建立:

1).下載http://www.lua.org/versions.html#5.3

2).下載tolua-5.2.4

Tulua官網http://webserver2.tecgraf.puc-rio.br/~celes/tolua/,更新到tolua-5.2.4,支持lua5.2.4。官網只提供了tolua的源代碼,沒有提供任何程序。

下載代碼解壓後,在src目錄下有三個目錄,如下:

Bin目錄中包含了生成tolua++.exe轉換程序的代碼,我以使用VS2015編譯,文章最後有下載地址。

Lib目錄包含了程序使用tolua時需要包含的庫的代碼,因爲代碼比較少,我一般直接將lib文件夾中的代碼直接包含到程序中。

Tests目錄包含了tolua的一些例子,這些例子我以全部使用VS2015進行了編譯,文章最後有下載地址。

3) VS2017工程建立

a.  lua5.3.5: 在項目中去除掉lua.c和luac.c文件.

b.  tolua在Bin目錄下有兩個.c文件,tolua.c、toluabind.c,將這兩個文件加入到項目中,另外項目中還須要lua5.2.4代碼和Lib目錄下的代碼.。如下:

 

1. tolua++.exe 生成

2. tolua++.lib

修改完成後再點擊編譯,終於生成“tolua++.exe”文件了:

編寫pkg文件

pkg文件語法,這裏不講解,具體情況tolua官網:http://webserver2.tecgraf.puc-rio.br/~celes/tolua/tolua-3.2.html。語法規則不多,與C++非常接近,很容易看懂。

 

導出源文件

上面講了使用 tolua 的三部曲,下面使用實際例子講解一下。首先,正常編寫 c++ 代碼,這裏我們創建一個類

原始頭文件

//mylib.h
class Test
{
public:
    Test(int a, int b);
    ~Test();
    void sayHello();
    int add();
    int getA();

private:
    int a;
    int b;
};

 原始源文件

//mylib.cpp
#include "mylib.h"
#include <iostream>

Test::Test(int a, int b)
{
    this->a = a;
    this->b = b;
}

Test::~Test()
{
}

void Test::sayHello()
{
    std::cout << "hello world" << std::endl;
}

int Test::add()
{
    return this->a + this->b;
}

int Test::getA()
{
    return this->a;
}

  

package 文件

$#include "mylib.h"
class Test
{
    Test(int, int);
    ~Test();
    void sayHello();
    int add();  
    int getA();
};

 可以看到 package 文件和 c++ 頭文件基本一致,要注意的是要在文件頭引入頭文件,然後把 public 關鍵字去掉。所有公有的函數或數據都可以導出,如果不想導出某個函數,則在 package 文件中不要定義就可以了。

然後打開命令行,輸入下面的命令

tolua -n mylib -o tolua.cpp mylib.pkg

   

導出的文件名可以任意命名,但因爲我們已經有一個原始的源文件 mylib.cpp 了,所以這裏不能將導出的源文件命名爲 mylib.cpp,否則後面使用的時候就會有問題,這裏我命名爲 tolua.cpp。還有一個要注意的就是必須把 mylib.h 跟 mylib.pkg 放在一起,因爲 package 文件需要用到頭文件(第一行就已經引入頭文件了)

現在我們有了 mylib.h、mylib.cpp 和 tolua.cpp 這三個文件,接下來就可以在項目中使用了
在 c++ 程序中使用 tolua

新建一個 c++ 控制檯程序,因爲要使用到 lua 和 tolua,所以要把相應的頭文件和庫文件包含進來,頭文件有 lua.h、lualib.h、lauxlib.h、lua.hpp、luaconf.h 和 tolua.h,庫文件則有 lua.lib 和 tolua.lib。

首先,我們先來測試一下 lua 環境,新建一個 main.cpp 文件,輸入下面代碼

//main.cpp
#include <iostream>
extern "C"
{
#include "lualib.h"
#include "lauxlib.h"
}

using namespace std;

int main()
{
    int tolua_mylib_open(lua_State*);
    lua_State* state = luaL_newstate();
    luaL_openlibs(state);

    if (luaL_dostring(state, "print([[hello world]])") != 0)
    {
        cout << "excute lua file failed!" << endl;
    }
    lua_close(state);

    system("pause");
    return 0;
}

   

如果正確打印出 “hello world”,則說明 lua 環境沒有問題,否則就檢查一下頭文件和庫文件是否正確引入了

接下來把 mylib.h、mylib.cpp 和 tolua.cpp 這三個文件添加到項目中,我們先來分析下 tolua.cpp 這個文件的內容

static int tolua_collect_Test (lua_State* tolua_S){}

static void tolua_reg_types (lua_State* tolua_S){}

//對應構造函數
static int tolua_mylib_Test_new00(lua_State* tolua_S){}

//對應析構函數
static int tolua_mylib_Test_delete00(lua_State* tolua_S){}

//sayHello
static int tolua_mylib_Test_sayHello00(lua_State* tolua_S){}

//add
static int tolua_mylib_Test_add00(lua_State* tolua_S){}

//getA
static int tolua_mylib_Test_getA00(lua_State* tolua_S){}

LUALIB_API int luaopen_mylib (lua_State* tolua_S){}

TOLUA_API int tolua_mylib_open (lua_State* tolua_S){}

   

這裏只列出主要的幾個函數,可以看到 tolua 在導出 c++ 源碼的時候爲每個函數都生成一個對應的靜態函數;除此之外,還有幾個重要的函數,tolua_collect_Test 用於垃圾回收,tolua_reg_types 用於註冊類名,toluaopen_mylib 用於打開庫函數,tolua_mylib_open 用於打開 tolua,這是我們唯一關心的函數,在使用 tolua 之前必須先調用這個函數,這樣所有導出的 c++ 函數就可以在 lua 中使用了

接下來開始測試在 lua 中訪問 c++ 函數,新建一個 test.lua 文件,輸入下面代碼

local test = Test:new(1, 2)
test:sayHello()
print("a = " .. test:getA())
print("a + b = " .. test:add())

 

然後修改 main.cpp 文件

#include <iostream>
extern "C"
{
#include "lualib.h"
#include "lauxlib.h"
}
#include "mylib.h"

using namespace std;

int main()
{
    int tolua_mylib_open(lua_State*);
    lua_State* state = luaL_newstate();
    luaL_openlibs(state);
    tolua_mylib_open(state);


    if (luaL_dofile(state, "scripts/test.lua") != 0)
    {
        cout << "excute lua file failed!" << endl;
        lua_close(state);
        return 1;
    }
    lua_close(state);

    system("pause");
    return 0;
}

  

首先,要引入 mylib.h 頭文件,然後調用 tolua_mylib_open(state); 打開 tolua,這個函數在 tolua.cpp 文件中定義和實現,main.cpp 並不知道這個函數,所以要在使用前手動定義一下 int tolua_mylib_open(lua_State*);,之後就可以執行 test.lua 文件了

如果沒錯誤,將會看到下面的執行結果

如果沒錯誤,將會看到下面的執行結果

tolua

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章