過去在專案中接觸 Lua 腳本,多半是參考現有代碼或模仿前人寫法,對於 Lua 與 C 語言底層如何交互並未深入理解。今天決定親手寫一個完整範例,記錄從環境搭建到雙向調用的全過程,希望能幫助有相同疑惑的開發者快速入門。
需求很簡單:計算 x + y。但 x 和 y 會隨時變動,若硬編碼在 C 程式裡,每次修改都得重新編譯,極不靈活。解決方案是將這兩個參數放入 Lua 腳本,由 C 程式讀取腳本並調用 Lua 定義的邏輯,再將結果回傳給 C。
本範例使用 Visual Studio 2005 (VS2005) 作為開發工具。Lua 庫的下載與配置網路上資源豐富,此處不贅述,重點在於專案屬性中正確設定「附加包含目錄」與「附加程式庫目錄」,並將 lua5.1.lib (或對應版本) 加入連結器輸入。
核心思路:初始化 Lua 虛擬機 → 開啟標準庫 → 將 C 函數註冊為 Lua 全域函數 → 載入並執行 Lua 腳本檔 → 從 Lua 調用 C 函數並取得結果。
[cpp]
// testlua.c
#include "stdafx.h"
#include <stdio.h>
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
lua_State* L;
// C 函數原型:供 Lua 調用
int add(lua_State* L);
// C 函數實現:從堆疊取兩個整數相加並印出
int add(lua_State* L)
{
// 從堆疊索引 1、2 取整數並做型別檢查
int x = luaL_checkint(L, 1);
int y = luaL_checkint(L, 2);
printf("result:%d\n", x + y);
return 1; // 返回值數量 (此處無返回值給 Lua,僅為演示)
}
int _tmain(int argc, _TCHAR* argv[])
{
// 1. 初始化 Lua 狀態機
L = luaL_newstate();
// 2. 開啟所有標準庫
luaL_openlibs(L);
// 3. 將 C 函數 add 推入堆疊
lua_pushcfunction(L, add);
// 4. 設為全域名 "ADD",Lua 端即可用 ADD() 調用
lua_setglobal(L, "ADD");
// 5. 載入 Lua 腳本檔 (請依實際路徑修改)
if (luaL_loadfile(L, "E:\\work\\vsProject\\testLua\\mylua.lua")) {
printf("error: cannot load script\n");
return -1;
}
// 6. 執行腳本 (編譯並執行全域代碼,定義 mylua 函數)
lua_pcall(L, 0, 0, 0);
// 7. 取得 Lua 全域函數 mylua 並執行
lua_getglobal(L, "mylua");
lua_pcall(L, 0, 0, 0);
printf("hello my lua\n");
return 0;
}
腳本非常簡潔,定義一個 mylua 函數,內部呼叫 C 註冊的 ADD 函數兩次。
[lua]
function mylua()
print("mylua")
ADD(1, 2) -- 呼叫 C 函數 add(1,2)
ADD(3, 4) -- 呼叫 C 函數 add(3,4)
end
編譯執行後,控制台輸出如下:
mylua result:3 result:7 hello my lua

流程驗證成功:Lua 腳本中的 ADD(1,2) 正確關聯到 C 函數 add,參數經由 Lua 堆疊傳遞,C 端取出運算並印出結果。這個最小化範例涵蓋了「C 向 Lua 註冊函數」與「Lua 調用 C 函數」兩大核心機制,理解此流程即可舉一反三處理更複雜的數據交換與邏輯分離。