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");
// 設定全域變數
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))");
封裝輔助類別 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()
);
LuaModule(state, "mymodule")
.def("add", add)
.def("add2", test, &Test::add);
state->DoString(
"print(mymodule.add(3,4))"
"print(mymodule.add2(3,4))"
);
// 建立表格並設定鍵值
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 為鍵查找
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 官方說明。