本文參考了某大佬的部落格,寫得十分詳細,推薦!!!
需求:
在之前的求解器中新增了Lua庫,使得程式可以在Lua指令碼中實現自定義函數功能,考慮到未來可能需要與第三方程式庫進行耦合計算,現在想到可以藉助Lua指令碼,在指令碼中呼叫第三方動態庫,以實現其功能的擴充套件。接下來將要簡要記錄下Lua中呼叫第三方庫的實現過程。
在windows平臺下,藉助mingw編譯器進行編譯。
首先需要去下載Lua原始碼,這裡下載的是最新的Lua5.4
在安裝路徑下進行編譯,原始碼中已經寫好了Makefile,可以直接進行編譯
mingw32-make mingw
mingw32-make install local
在install目錄下得到lua.exe,lua54.dll,liblua.a 等可執行檔案,動態庫與靜態庫
以下給出了一個範例,註釋比較詳細
cpp2dll.cpp
#include <Windows.h>
#include "lua.hpp"
#include <iostream>
#include <time.h>
#include <cmath>
// 函數範例:引數輸入順序
int Lua_printf(lua_State *L)
{
int n = lua_gettop(L); // 判斷輸入引數個數
switch (n)
{
case 0:
std::cout << "intput Para Number is 0" << std::endl;
break;
default:
std::cout << "intput Para is " << n << std::endl;
int a = 0;
for (int i = 1; i <= n; ++i)
{
a = lua_tonumber(L, i); // 從棧底,向上依次讀取資料
std::cout << a << " ";
}
std::cout << std::endl;
break;
};
return n; // 返回n個引數
}
int Lua_pow(lua_State *L)
{
int n = lua_gettop(L); // 判斷輸入引數個數
if (n != 2)
{
std::cout << "intput Para Number is not 2" << std::endl;
return -1;
}
double a, b, temp;
a = lua_tonumber(L, 1);
b = lua_tonumber(L, 2);
int re = std::pow(a, b);
std::cout << "a=" << a << "|b=" << b << "|re=" << re << std::endl;
// lua_pushstring(L, "re="); // 將返回結果壓入棧中
lua_pushnumber(L, re); // 將返回結果壓入棧中
// return 2;
return 1;
}
// 註冊名稱與函數的對應關係
static const luaL_Reg name_and_func[]{
{"printf", Lua_printf},
{"pow", Lua_pow},
{NULL, NULL}};
// 註冊函數:函數名稱"luaopen_xxx",其中,xxx必須是dll的名稱,即"xxx.dll"
extern "C"
{
int __declspec(dllexport) luaopen_cpp2dll(lua_State *L)
{
printf("start luaopen_lib\n");
luaL_newlib(L, name_and_func); // 建立一個新表,並將函數入棧
printf("end luaopen_lib\n");
return 1;
}
}
編譯時需要連結到Lua生成的靜態庫,所以g++編譯時需要指定lua標頭檔案路徑,以及靜態庫路徑,編譯命令如下
g++ cpp2dll.cpp -O3 -o cpp2dll.dll -shared -fPIC -I ./lua54/include -L absolute/path/to/lua54/lib -llua54
至此生成得Lua可以識別的動態連結庫cpp2dll.dll
編寫如下的Lua指令碼
test.lua
local cpp2dll = require("cpp2dll")
cpp2dll.printf()
cpp2dll.printf(0,1,2,3)
a=2
b=10
print(a,"^",b,"=",cpp2dll.pow(a,b))
print(b,"^",a,"=",cpp2dll.pow(b,a))
lua.exe 執行test.lua指令碼
得到如下輸出
cmd$ lua.exe test.lua
start luaopen_lib
end luaopen_lib
intput Para Number is 0
intput Para is 4
0 1 2 3
a=2|b=10|re=1024
2 ^ 10 = 1024.0
a=10|b=2|re=100
10 ^ 2 = 100.0
最後,在Lua指令碼中成功呼叫C++編寫的動態連結庫