Lua与C++交互调用(1)

本文介绍Lua脚本如何调用C++接口,包括创建C++动态链接库、注册Lua函数及Lua脚本调用方法。通过具体示例,帮助读者理解lua_State和luaL_reg的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

1 Lua脚本对c++接口的调用

 

1.1   简单示例

Lua脚本通过c++链接库调用c++提供的接口。c++提供的链接库需要按某种“样式”书写,才能够被lua脚本调用。

先通过一个简单示例来给大家一个很初步的认识:

首先建立一个空的c++动态链接库程序;

在其中建立test.htest.cpp两个文件,其内容如下:

 

// test.h

// include headers

extern "C"

{

#include "lua.h"

#include "lualib.h"

#include "lua.hpp"

}

 

// export to lua functions

static int Lua_TestA(lua_State* L);

static int Lua_TestB(lua_State* L);

 

// reg exporting lua functions to lua

static const LuaL_reg LUADllFunctions[] =

{

{"TestA",Lua_TestA},

{"TestB",Lua_TestB},

{NULL,NULL}

}

 

// dll export function

extern "C"

{

int __declspec(dllexport) LibExportFun(Lua_State* L);

}

 

// test.cpp

//

#include "test.h"

 

#include <string>

#include <windows.h>

 

int LibExportFun(lua_State* L)

{

luaL_openlib(L,"LUALibFuns",LUADllFunctions,0);

return 1;

}

 

int Lua_TestA(lua_State* L)

{

// 弹出消息框

MessageBox(NULL,"Test In C","Test",MB_OK);

return 1;

}

 

int Lua_TestB(lua_State* L)

{

// add two string

 

// 获取参数个数

int iNum = lua_gettop(L);

if(iNum != 2)

return 0;

 

// string A

size_t lenA;

const char* sA = lua_tolstring(L,1,&lenA);

 

// string B

size_t lenB;

cong char* sB = lua_tolstring(L,2,&lenB);

 

std::string strA = sA;

std::string strB = sB;

 

std::string strRe = sA + sB;

 

// 参数返回

lua_pushstring(L,strRe.c_str());

 

return 1;

}

 

以上部分为c++链接库部分需要完成工作,下边就是如何在Lua脚本中调用上边提供的接口,当然,首先需要将编译的c++链接库编译正确。

 

Lua脚本调用示例:

local dll = "E:/test/test.dll";   -- 实际使用时请输入链接库的绝对文件路径

local testlib = package.loadlib(dll,"LibExportFun");

if !testlib then

-- end

end

 

-- 相当于调用链接库的导出函数

testlib();

 

-- 因为在连接库的导出函数中完成了函数的注册,所以此时可以安全的 调用链接库提供的接口函数了

LUALibFuns.TestA();

sRe = LuALibFuns.TestB("TA","TB");

print(sRe);  -- 应该输出TATB

 

到此,希望您将上边所有代码自己编译、运行下,然后运行下我们的lua脚本,发现接口被正确调用了吧。如果是刚刚接触Lua的同学,是不是很激动啊,下边我们会继续稍微深入研究每条语句的含义,同时会做一些相应的扩展。

 

1.2   深入理解,举一反三

在头文件Test.h中,我们会看到两个以前没有见过的标识符,lua_StateLuaL_reg。它们是什么?用来做什么用?

 

lua_State:

lua_State的分析,我们首先的认知是,它是一个函数参数。暂时,我们假设Lua脚本在调用我们导出的函数时,自动将参数组合成一个统一的lua_State结构,这样来完成通信。

 

luaL_reg:

我们可以在代码中查看到luaL_reg的定义:

typedef struct luaL_Reg {

  const char *name;

  lua_CFunction func;

} luaL_Reg;

它是一个结构,一个通过名字描述一个对应的函数。我们再来看lua_CFunction函数定义;

typedef int (*lua_CFunction) (lua_State *L);

可以发现,我们导出给Lua脚本使用的函数必须返回int型,并且参数为lua_State*。这样我们就可以理解为什么我们两个导出给lua脚本使用的函数定义形式必须那个样子。

 

也许您会问,为什么必须设计的传递lua_State*这个类型的参数?这样有个好处,接口统一,关于这点有点类似下边的情况,

假设你提供了一个链接库供其它人使用,接口形式如int add(int,int);是计算两个数的和,平时运行的很好,但有一天用户希望能够直接完成三个数的求和,这样就不需要分两次调用接口了,如何更改呢?很可能会添加一个接口形式如int add(int,int,int),这样调用者很可能需要重新编译程序,这样比较麻烦,所以一个库的接口一定要设计的具有比较好的扩展性,尽量保持接口的稳定,统一性。

 

今天暂时先写到这里,改天继续写。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值