首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

使用 LuaPlus 實現 C++ 與 Lua 腳本無縫整合

     編輯:關於C++

前言:為何選擇 LuaPlus?

LuaPlus 是建立在 Lua 原始碼之上的 C++ 增強庫,提供更符合 C++ 慣用語的 API,降低整合複雜度。本文基於 LuaPlus for Lua 5.01 Build 1080(2004/02/28)示範核心用法。

下載連結:
原始碼:LuaPlus50_Build1081.zip
Win32 二進制:LuaPlus50_Build1081_Win32Binaries.zip

一、建立狀態機與執行腳本

// 建立 Lua 狀態機(RAII 管理生命週期)
LuaStateOwner state;

// 直接執行字串腳本
state->DoString("print('Hello World\\n')");

// 載入並執行 .lua 檔案
state->DoFile("C:\\test.lua");

// 載入並執行預編譯 .luac 檔案
state->DoFile("C:\\test.luac");

二、C++ 與 Lua 雙向資料交換與函數呼叫

// 設定全域變數
state->GetGlobals().SetNumber("myvalue", 123456);

// 讀取全域變數
int myvalue = state->GetGlobal("myvalue").GetInteger();

// 呼叫 Lua 函數(print 為內建)
LuaFunction<int> luaPrint = state->GetGlobal("print");
luaPrint("Hello World\n");

// 註冊 C 函數供 Lua 呼叫
int add(int a, int b) { return a + b; }
state->GetGlobals().RegisterDirect("add", add);
state->DoString("print(add(3,4))");  // 輸出 7

// 註冊 C++ 成員函數供 Lua 呼叫
class Test { public: int add(int a, int b) { return a + b; } };
Test test;
state->GetGlobals().RegisterDirect("add", test, &Test::add);
state->DoString("print(add(3,4))");

三、在 Lua 中使用 C++ 類別(需 LuaPlusHelper.h)

封裝輔助類別 LuaPlusHelper.h 簡化類別綁定。限制:不支援虛擬函數、成員變數不可直接存取(需透過 Getter/Setter)。

// 範例 C++ 類別
class Logger {
public:
    void LOGMEMBER(const char* msg) { printf("In member: %s\n", msg); }
    Logger() { v = 10; }
    virtual ~Logger() {}
    Logger(int n) {}
    Logger(Logger* l) { l->LOGMEMBER("Call From Constructor"); }
    int SetValue(int val) { v = val; return 0; }
    int GetValue() { return v; }
    int v;
};

// 綁定到 Lua
LuaClass<Logger>(state)
    .create("Logger")           // Logger()
    .create<int>("Logger2")     // Logger(int)
    .create<Logger*>("Logger3") // Logger(Logger*)
    .destroy("Free")            // 顯式釋放
    .destroy("__gc")            // GC 自動釋放
    .def("lm", &Logger::LOGMEMBER)
    .def("SetValue", &Logger::SetValue)
    .def("GetValue", &Logger::GetValue);

// Lua 端使用(方式 1:手動管理生命週期)
state->DoString(
    "l = Logger()"
    "l.lm('Hello World 1')"
    "l.Free()"
);

// 方式 2:GC 自動管理
state->DoString(
    "m = Logger(10)"
    "m.lm('Hello World 2')"
    "n = Logger(m)"
    "n.lm('Hello World 3')"
    "m.SetValue(11)"
    "print(m.GetValue())"
    "m, n = nil, nil"  // 觸發 GC 呼叫 ~Logger()
);

四、將 C 函數組織為 Lua 模組

LuaModule(state, "mymodule")
    .def("add", add)
    .def("add2", test, &Test::add);

state->DoString(
    "print(mymodule.add(3,4))"
    "print(mymodule.add2(3,4))"
);

五、操作 Lua Table 資料結構

// 建立表格並設定鍵值
LuaObject table = state->GetGlobals().CreateTable("mytable");
table.SetInteger("m", 10);
table.SetNumber("f", 1.99);
table.SetString("s", "Hello World");
table.SetWString("ch", L"你好");
table.SetString(1, "What");  // 數字鍵 1

// 相當於 Lua: mytable = {m=10, f=1.99, s="Hello World", ch=L"你好", "What"}

// Table 作為鍵/值
state->GetGlobals().CreateTable("nexttable")
    .SetString(table, "Hello")   // 以 table 為鍵
    .SetObject("obj", table);    // 以 table 為值

// 讀取表格內容
LuaObject t2 = state->GetGlobals()["mytable"];
int m = t2.GetByName("m").GetInteger();

LuaObject t3 = state->GetGlobals()["nexttable"];
std::string str = t3.GetByObject(t2).GetString();  // 以 table 為鍵查找

六、遍歷 Table

LuaStateOwner state;
state.DoString("MyTable = { Hi = 5, Hello = 10, Yo = 6 }");

LuaObject obj = state.GetGlobals()["MyTable"];
for (LuaTableIterator it(obj); it; it.Next()) {
    const char* key = it.GetKey().GetString();
    int num = it.GetValue().GetInteger();
    // 處理 key-value 對
}

結語

LuaPlus 配合 LuaPlusHelper.h 大幅降低 C++/Lua 綁定門檻。完整文件請參考 LuaPlus 官方說明。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved