lua与c++整合方案进阶

本文探讨了lua与C++整合中的痛点,如参数转换和管理,介绍了LuaBridge组件如何简化开发过程。作者选择luaBridge 2.6,重点讲解了初始化lua引擎、注册C++函数和类、cmake配置等关键步骤,并提供了相关资源链接和实例。

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

背景

之前的一篇文章lua与C++整合并互相调用_wp500的博客-CSDN博客,是对lua与C++整合进行了初步的尝试。不过在接下来实践中发现,开发的过程还是有很多不方便的地方。比如:

  • 注册到lua环境中的C++函数入参必须是 lua_State *L
  • 入参及返回类型,需要压栈及出栈
  • lua类型与c++类型不同,需要进行转化

以上问题让开发者增加了很多的额外的工作量,为了简化整合的步骤。当前有很多组件来解决以上痛点,给开发人员增效。

常用的组件

  • LuaPlus
  • luabind
  • tolua++
  • luaBridge

方案

精力的原因,我没有详细对比这些组件,直接选择了luaBridge作为解决方案 。理由是LuaBridge其中的一个特性是集成到项目非常的便捷,只要把头文件加入到项目中就可以了。

luaBridge的特性

  • 软件准守与MIT许可(该许可赋予被许可人非常的宽松权利)
  • 可打印的开发手册(同样适用MIT许可)
  • 整合只需要引入头文件,而不需要额外的Makefile,.cpp等文件。仅仅#include头文件(我看到这个点,就动心了。决定试用一下)
  • 简单、轻量级、无其他依赖
  • 也不需要宏定义、配置、或者使用其他的配置脚本等
  • 支持对不同对象的生命周期进行管理
  • 方便、安全的访问Lua栈
  • 可以自动化绑定函数的入参
  • 简化访问lua特定的对象
  • debug简便、快捷

注意:这个我采用luaBridge版本是2.6对应整合的lua版本是5.1。我最开始用的是lua5.4发现不能很好的和luaBridge2.6进行整合,后来换成了lua5.1之后整合成功。而想要整合lua5.4版本也要把luaBridge升级到3.0。这个也是我遇到的一个困扰我挺长时间的一个大坑。

luaBridge资源

  • luaBridge2.6 (https://github.com/vinniefalco/LuaBridge)
  • luaBridge 2.6 的手册 (http://vinniefalco.github.io/LuaBridge/Manual.html#s2.6)
  • luaBridge 3.0 (https://github.com/kunitoki/LuaBridge3)
  • luaBridge 3.0 的手册 (https://kunitoki.github.io/LuaBridge3/Manual)

实践

这块原本想引用一起我项目中的代码,最后觉得还是手册里的样例更方便理解。

初始化lua引擎

这部分其实luaBridge还没有登场,是对lua引擎完成初始化工作

lua_State* L=luaL_newstate();
luaL_openlibs(L);

有了以上两句就创建了一个lua的引擎。到这里就完成了准备的工作

将C++函数、类、变量注册到lua引擎中

如果将C++函数注册到lua引擎中,首先要指定注册到哪个namespace(命名空间),这点和c++类似。Lua本身有一个全局的命名空间,还可以自定义多个子命名空间。而子命名空间都要隶属于全局的命名空间中。
注册的样例如下:

  1. 注册一个函数test
  2. 注册一个类A
  3. 注册A类的子类B
  4. 注册一个变量var1,var2到不同的命名空间
//先要获取全局命名空间
class A
{
public:
    A( )
    {

    }
    virtual void foo( int a )
    {
        printf("foo base
");
    }

    std::string Member;
};

class B : public A
{
public:
    virtual void foo( int a )
    {
        printf("foo inherited
");
    }
};

void foo( int b )
{

}
//注册普通函数
int test(int arg)
{
	return 1;
}

//注册普通变量
int var1; 
int var2;

luabridge::Namespace luans=luabridge::getGlobalNamespace(L);
			 luans.addFunction("test",test); //<-- 1. 注册了一个函数,这里入参和返回值直接被luabridge绑定
        luans.beginClass<A>("Sobj")
            .addConstructor<void (*) (void)> ()
            .addFunction("foo", &A::foo)
            .addData("Member",&A::Member)
        .endClass()  //<-- 2. 注册了一个类,并声明了对象的构造函数和其他成员函数,可以在lua中直接创建这个对象,并使用注册的成员函数及成员变量
        .deriveClass<B, A>("SSec")
            .addFunction("foo",&B::foo )
        .endClass();  //<-- 3. 注册了A的子类
        
        luans.addProperty ("var_global", &var1);//<-- 4.1 把var1注册到全局命名空间
        luans.beginNamespace ("test") //
    			.addProperty ("var_test", &var2) //<-- 4.2 把var1注册到test的命名空间中
  		  .endNamespace ();
  • lua侧的代码
--case1
print(test(1))
--case2
local a = Sobj()
a:foo(2)
a.Member = "hello"

--case3
local b= SSec()
b::foo(2)

--case4.1
var_global=5;
--case4.2
test.var_test=6;

c++代码触发lua脚本的执行

我们大多数项目中是通过C++来调用lua脚本。按照之前的步骤我们初始化了Lua的引擎,并将C++相关函数、类、变量注册到了lua引擎中之后。我们可以调用lua脚本的执行,而方法非常简单只是一句就可以了

luaL_dostring(L,script); 

cmake操作

由于我刚学习c++及cmake,这里在最后额外说一下相关的配置。
执行代码需要依赖Lua的动态链接库,使用cmake在CMakeLists.txt中加入

target_link_libraries(robot_control_demo PRIVATE "/usr/local/Cellar/lua@5.1/5.1.5_8/lib/liblua.5.1.5.dylib")

这里的路径是mac系统典型的动态链接库的路径,其他系统换成对应的路径即可。

最后执行编译工程

#工程目录下
mkdir build
#进入编译目录
cd build
cmake .. 
cmake --build . 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wp500

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值