使用SWIG在C++中包装Lua对象 SWIG是一种工具,用于在C++和其他语言之间进行互操作性。使用SWIG可以将Lua对象包装为C++对象,使其可以在C++代码中使用。 为了使用Lua对象,首先需要在C++中包含Lua头文件: ``` #include <lua.hpp> ``` 然后可以使用SWIG的lua指令将Lua对象包装到C++中。例如,可以将以下代码添加到SWIG接口文件中: ``` %module mymodule %{ #include "myclass.h" %} %include "myclass.h" %{ void myLuaFunc(lua_State* L) { MyClass* obj = new MyClass(); lua_pushlightuserdata(L, obj); } %} %luaconst(MyConst) 23 %luamethods(MyClass) MyClass* new_MyClass() { return new MyClass(); } void delete_MyClass(MyClass* obj) { delete obj; } int MyClass_getX(MyClass* obj) { return obj->getX(); } void MyClass_setX(MyClass* obj, int x) { obj->setX(x); } %enddef %inline %{ void myCFunc(MyClass* obj) { obj->doSomething(); } %} ``` 此示例中,将包装名为“mymodule”的C++类“MyClass”。SWIG提供了一种方法将Lua函数包装到C++中,并且还定义了一些包装函数用于访问MyClass的成员函数和数据成员。 要使用这些包装函数,需要将SWIG接口文件编译为与应用程序链接的C++库。然后可以在C++代码中包含生成的头文件并使用包装的函数。 ``` #include "mymodule_wrap.h" int main() { lua_State* L = luaL_newstate(); luaL_openlibs(L); mymodule_init(L); lua_pushcfunction(L, myLuaFunc); lua_setglobal(L, "myLuaFunc"); MyClass* obj = new_MyClass(); myCFunc(obj); int x = MyClass_getX(obj); MyClass_setX(obj, x + 1); delete_MyClass(obj); lua_close(L); return 0; } ``` 此代码创建了一个新的Lua状态,并使用mymodule_init函数初始化 SWIG包装。然后将myLuaFunc函数从C++代码中推入Lua中。接下来,使用C++包装函数访问MyClass对象的成员函数和数据成员。最后,当程序退出时,关闭Lua状态。 通过SWIG,将Lua对象包装为C++对象,可以方便地在C++代码中使用Lua。

目前我知道如何使用SWIG绑定在Lua中实例化和传递C++对象,我需要的是相反的情况。

我正在使用Lua和C++和SWIG。

我有C++中的接口和Lua中的对象,它们实现了执行同样工作且具有相同结构的方法。我想能够在Lua中实例化这些对象,但使用指向它们类似的接口的指针在C++中传递它们。

因此,我可以想象创建一个C++实现的接口,它将作为所述Lua对象的处理程序,但我不知道如何做到这一点。该类将在C++世界中充当Lua对象的代表或代理。

为了澄清,我将从类似问题的答案中使用的以下示例代码开始:

C++代码:

// Represents a generic bank account class Account {     virtual void deposit(double amount) = 0; };

Lua代码:

SavingsAccount = { balance = 0 } SavingsAccount.deposit = function(amount)     SavingsAccount.balance = SavingsAccount.balance + amount end

--Usage a = SavingsAccount a.balance = 100 a.deposit(1000)

现在假设我有一个名为Bank的C++类:

class Bank {     void AddAccount(Account *a); };

这里我想要的机制是在Lua中执行以下操作:

SavingsAccount = { balance = 0 } SavingsAccount.deposit = function(amount)     SavingsAccount.balance = SavingsAccount.balance + amount end

--Usage a = SavingsAccount bank:AddAccount(a)

如果我需要采取额外的步骤,如实例化C++类以充当代理并将其传递给具有所有Lua函数等的Lua表,我可以想象它看起来像这样:

C++代码:

// Represents a generic bank account class ProxyAccount : public Account {     virtual void deposit(double amount); };

Lua代码:

SavingsAccount = { balance = 0 } SavingsAccount.deposit = function(amount)     SavingsAccount.balance = SavingsAccount.balance + amount end

--Usage a = SavingsAccount a.balance = 100 a.deposit(1000)

proxy = program.ProxyAccount() proxy.settable(a) bank:AddAccount(p)

问题在于我不知道如何实现ProxyAccount类,甚至不知道settable函数的函数签名会是什么样的...

原文链接 https://stackoverflow.com/questions/1792678

点赞
stackoverflow用户48940
stackoverflow用户48940

你可以绑定任何你想要的 C 函数到 Lua 并从那里调用它。你可以在这个函数中定义你期望的脚本和你的 C++ 代码之间的合同。例如,以下代码会做你想要的事情。你需要向你的 Lua 表中添加元表信息,以便你可以区分不同的 Lua 对象类型。

int lua_AddBankAccount(lua_State* L, int pos)
{
    // 假设你已经为你的 Lua 对象创建了元数据。
    if (IsAccount(L, pos))
    {
       // 处理 'Account' Lua 实例。
    }
    else
    {
       // 错误 - 尝试添加一个非账号实例。
    }
}

你可以使用 SWIG 进一步绑定任意 C 方法,但基本上相同。

2009-11-24 21:54:54
stackoverflow用户18265
stackoverflow用户18265

我对 SWIG 不是很熟悉(我知道它是什么,但从未使用过),所以这可能不是你要找的答案。

我一直在使用 C++ 项目,并成功地使用了 luabind。它允许您使用 Lua 对象 子类化 C++ 对象。您可能想尝试一下并查看是否适合您。

2009-12-29 20:10:50
stackoverflow用户137828
stackoverflow用户137828

从你的例子和讨论中我似乎理解到你期望 Lua 是主要语言,而 C++ 是客户端。然而问题是 Lua C 接口并不是被设计成这样工作的,Lua 应该是客户端,所有的重活都应该由 C 写,这样 Lua 才能轻松地调用它。

现在最重要的问题是:为什么你不想用 C 作为对象的表示,而更喜欢使用 Lua?因为 C++ 是一门更底层的语言,对象的定义必须是静态的,而 Lua 则动态定义其 “对象”,因此让 Lua 适应 C++ 对象更为容易。

我还看到另一个问题,你似乎正在以一种极其面向对象的方式设计 Lua 代码。请记住,尽管 Lua 可以模拟面向对象的概念,但它不是一种面向对象的语言,也不应该主要用作面向对象语言。如果你需要一个完全面向对象的脚本语言,使用 Python 更好。

现在,如果你真的想用另一种方式实现,而且认为其他选择都不适合你,那么我建议你将 Lua 对象保留为一个协程,这样可以:

  • 在 C++ 中保留对象的表示 (lua_State *)
  • 拥有多个相同“对象类型”的单独实例
  • Lua 负责清理

然而,缺点是:

  • 所有作用于 “对象”的函数都需要通过 Lua API 执行
  • 没有易于/快速地识别不同 Lua 类型的方法 (可以使用元表)
  • 实现相当繁琐,难以理解。

编辑: 这里是如何在脚本中公开对象接口的方法,每个对象实例将运行一个新的 lua_State,并单独运行其脚本,从而允许 “对象成员数据” 只是脚本实例中的全局变量。实现对象方法的 API 如下:

int move(lua_State * L)
{
  int idx = lua_getglobal(L, "this");
  assert(!lua_isnull(-1));
  AIObject * obj = static_cast<AIObject *>(lua_touserdata(L, -1));
  lua_pop(1);
  //Pop the other parameters
  obj->move(/*params*/);
}
2009-12-30 09:53:01