Lua的VS安装参考此文:
本文会通过一些示例展示如何用lua调用C/C++传递过来的函数,并辅以部分解释语句:
Lua中调用C/C++函数简介:
C/C++注册函数给lua的方式有多种
lua_register
通过 _G 表间接地将函数注册到全局环境中lua_pushcfunction
到栈里再通过lua_setglobal
取出注册到_G表里或者通过lua_rawsetfield
/lua_setfield
注册到特定的表里#include <stdio.h>
#include <lua.hpp>
extern "C" {
// 一个Lua函数的标准模型
LUALIB_API int lua_TestFunc2(lua_State* L)
{
printf("lua调用C函数\n");
// 表示有0个返回值
return 0;
}
}
int main()
{
// 创建一个虚拟机
lua_State* L = luaL_newstate();
// 加载一些常用的系统库
luaL_openlibs(L);
// 注册一个函数给lua 以k v 的形式注册
lua_register(L, "testFunc", lua_TestFunc2);
/* 因为其宏定义为
* #define lua_register(L,n,f)
* (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
* 所以等价于
* 向栈中压入一个函数至栈顶
* lua_pushcfunction(L, lua_TestFunc);
* 将栈顶的名称元素设置名称为testFunc 在lua中可以范围该名称
* lua_setglobal(L, "testFunc");
*/
// 加载lua文件并执行
luaL_dofile(L, "Test2.lua");
// 关闭虚拟机
lua_close(L);
return 0;
}
-- Test2.lua
print("Lua_Hello World!")
testFunc()
#include <stdio.h>
#include <lua.hpp>
extern "C" {
// 一个Lua函数的标准模型
LUALIB_API int lua_TestFunc3(lua_State* L)
{
// 获取有几个参数
int top = lua_gettop(L);
printf("传入几个参数 top:[%d]\n", top);
// 下标从1开始 检查第一个参数是否为整型,是则返回整型
int num1 = luaL_checkinteger(L, 1);
int num2 = luaL_checkinteger(L, 2);
int num3 = luaL_checkinteger(L, 3);
printf("从栈底由下到上开始取数据:%d %d %d\n", num1,num2,num3);
int num4 = luaL_checkinteger(L, -1);
int num5 = luaL_checkinteger(L, -2);
int num6 = luaL_checkinteger(L, -3);
printf("从栈顶由上到下开始取数据:%d %d %d\n", num4, num5, num6);
lua_pushinteger(L, 999);// 压入第一个参数 整型
lua_pushstring(L, "hello World!!!!!");// 压入地二个参数 字符串
// 表示有2个返回值
return 2;
}
}
int main()
{
// 创建一个虚拟机
lua_State* L = luaL_newstate();
// 加载一些常用的系统库
luaL_openlibs(L);
// 注册一个函数给lua全局环境
lua_register(L, "testFunc", lua_TestFunc3);
// 加载lua文件并执行
if (luaL_dofile(L, "Test3.lua"))
{
// 在lua中 -1表示栈顶 如果出错 出错结果会放置在栈顶中
printf("%s\n", lua_tostring(L, -1));
}
// 关闭虚拟机
lua_close(L);
return 0;
}
通过从lua的栈里取出数据作为函数的参数使用
在push数据到lua的栈里后,需要函数的返回值告诉lua有几个返回值
Tips:
-- Test3.lua
print("Lua_Hello World!")
-- 传入参数 返回多个参数
local a,b = testFunc(123,1,2)
print(a..'===='..b)
#include <stdio.h>
#include <lua.hpp>
class MyClass {
private:
int _value;
public:
// 构造函数
MyClass(int value) : _value(value) {}
// 成员函数
void setValue(int newValue)
{
_value = newValue;
}
int getValue() const {
return _value;
}
};
extern "C" {
// 注册 C++ 类的方法
LUALIB_API int lua_myClassSetValue(lua_State* L) {
MyClass* obj = (MyClass*)lua_touserdata(L, 1);
int newValue = luaL_checkinteger(L, 2);
obj->setValue(newValue);
return 0;
}
LUALIB_API int lua_myClassGetValue(lua_State* L) {
MyClass* obj = (MyClass*)lua_touserdata(L, 1);
lua_pushinteger(L, obj->getValue());
return 1;
}
// 用于在 Lua 中创建 C++ 类的实例
LUALIB_API int lua_createMyClass(lua_State* L) {
int initialValue = luaL_optinteger(L, 1, 0);
MyClass* obj = new MyClass(initialValue);
lua_pushlightuserdata(L, obj);
return 1;
}
}
// 导入模块
int main() {
lua_State* L = luaL_newstate();
luaL_openlibs(L);
// 注册 C++ 类的方法
lua_register(L, "createMyClass", lua_createMyClass);
lua_register(L, "myClassSetValue", lua_myClassSetValue);
lua_register(L, "myClassGetValue", lua_myClassGetValue);
// 加载 Lua 脚本
luaL_dofile(L, "ClassToLua.lua");
// 清理资源
lua_close(L);
return 0;
}
通过lua_pushlightuserdata
将类的指针暴露给lua,然后类成员函数通过lua_touserdata获得lua传过来的类的指针。
-- ClassToLua.lua
-- 创建一个 MyClass 实例
local myObject = createMyClass(10)
-- 获取值
local val = myClassGetValue(myObject)
print(val) -- 输出: 10
-- 设置值
myClassSetValue(myObject, 20)
-- 获取值
local val = myClassGetValue(myObject)
print(val) -- 输出: 20
#include <iostream>
#include <lua.hpp>
using namespace std;
class AdapterTest
{
private:
int _value;
public:
AdapterTest(int value) :_value(value) {}
int GetValue() { return _value; }
};
AdapterTest* obj = new AdapterTest(10);
int AdapterFuncToLua(lua_State* L)
{
// 获取对象的值
int value = obj->GetValue();
// 将值压入Lua栈顶,这样Lua才能访问它
lua_pushinteger(L, value);
// 返回栈顶元素的数量(这里是1)
return 1;
}
//AdapterFuncToLua 将类成员函数转变为lua_CFunction的形式供lua使用
int main()
{
// 创建一个虚拟机
lua_State* L = luaL_newstate();
// 加载一些常用的系统库
luaL_openlibs(L);
// 注册一个类的函数给lua
lua_register(L, "GetClassValue", AdapterFuncToLua);
// 加载lua文件并执行
luaL_dofile(L, "Test9.lua");
// 关闭虚拟机
lua_close(L);
return 0;
}
这里的关键是使用相应的函数来将C++中的类成员函数转换为Lua可以理解的lua_CFunction形式
-- Test9.lua
print(GetClassValue) -- 打印函数地址
local value = GetClassValue()
print(value) -- 打印返回值10
注册函数给表分为逐个注册和批量注册的方式
#include <stdio.h>
#include <lua.hpp>
// 定义一个Lua函数
extern "C" {
LUALIB_API int lua_TestFuncTable(lua_State* L) {
printf("lua调用C函数\n");
return 0;
}
}
// 定义另一个Lua函数
extern "C" {
LUALIB_API int lua_TestFuncTable2(lua_State* L) {
int num1 = luaL_checkinteger(L, 1);
printf("传入参数: %d\n", num1);
lua_pushinteger(L, num1 * 2); // 返回参数的两倍
return 1;
}
}
int RgFuncToTable() {
// 创建一个虚拟机
lua_State* L = luaL_newstate();
// 加载一些常用的系统库
luaL_openlibs(L);
// 创建一个表
lua_newtable(L);
// 将函数注册到表中
lua_pushcfunction(L, lua_TestFuncTable);
lua_setfield(L, -2, "func1"); // -2 表示栈中倒数第二个元素,即刚创建的表
lua_pushcfunction(L, lua_TestFuncTable2);
lua_setfield(L, -2, "func2"); // -2 表示栈中倒数第二个元素,即刚创建的表
// 将表压入全局环境
lua_setglobal(L, "myTable");
// 加载lua文件并执行
if (luaL_dofile(L, "RgFuncToTable.lua")) {
// 在lua中 -1表示栈顶 如果出错 出错结果会放置在栈顶中
printf("%s\n", lua_tostring(L, -1));
}
// 关闭虚拟机
lua_close(L);
return 0;
}
-- RgFuncToTable.lua
print("RgFuncToTable.lua")
-- 调用表中的函数
myTable.func1()
local numTwo = myTable.func2(5)
print('num*2='..numTwo)
#include <stdio.h>
#include <lua.hpp>
#include <lauxlib.h>
// 定义Lua函数
extern "C" {
LUALIB_API int lua_TestFuncTable(lua_State* L) {
printf("lua调用C函数\n");
return 0;
}
LUALIB_API int lua_TestFuncTable2(lua_State* L) {
int num1 = luaL_checkinteger(L, 1);
printf("传入参数: %d\n", num1);
lua_pushinteger(L, num1 * 2); // 返回参数的两倍
return 1;
}
}
// 使用luaL_Reg批量注册函数
static const luaL_Reg methods[] = {
{"func1", lua_TestFuncTable},
{"func2", lua_TestFuncTable2},
{NULL, NULL} // 结束标志
};
LUAMOD_API int Lua_ModelTest(lua_State* L) {
// 创建一个表
lua_newtable(L);
// 批量注册函数到表中
luaL_setfuncs(L, methods, 0); // 第二个参数是methods数组,第三个参数是upvalues的数量,这里为0
return 1;
}
int main() {
// 创建一个虚拟机
lua_State* L = luaL_newstate();
// 加载一些常用的系统库
luaL_openlibs(L);
luaL_requiref(L, "myTable", Lua_ModelTest, 1);
//or
// lua_newtable(L);
// luaL_setfuncs(L, methods, 0);
// lua_setglobal(L, "myTable");
// 加载lua文件并执行
if (luaL_dofile(L, "RgFuncToTable.lua")) {
// 在lua中 -1表示栈顶 如果出错 出错结果会放置在栈顶中
printf("%s\n", lua_tostring(L, -1));
}
// 关闭虚拟机
lua_close(L);
return 0;
}
-- RgFuncToTable.lua
print("RgFuncToTable.lua")
-- 调用表中的函数
myTable.func1()
local numTwo = myTable.func2(5)
print('num*2='..numTwo)
本文列出的是一些简单的Lua调用C/C++函数的示例,还有许多方式例如将C函数库变成一个dll模块让Lua调用等等,本文暂不收录示例,感兴趣可以自行搜索。
编译成DLL模块可参考文章:
有疑惑的地方可以参考:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。