2

目前我知道如何使用 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;
};

卢阿代码:

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

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

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

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);
};

卢阿代码:

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 的函数签名会是什么样子......

4

3 回答 3

3

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

我一直在研究一个 C++ 项目,并且使用luabind取得了成功。它允许您使用 Lua 对象对 C++ 对象进行子类化。您可能想尝试一下,看看它是否适合您。

于 2009-12-29T20:10:50.023 回答
2

我似乎从您的示例和讨论中收集到的是,您期望 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-30T09:53:01.283 回答
1

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

int lua_AddBankAccount(lua_State* L, int pos)
{
    // Assume you've created metadata for your Lua objects.
    if (IsAccount(L, pos))
    {
       // process your 'Account' Lua instance.
    }
    else
    {
       // error - tried to add a non-Account.
    }
}

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

于 2009-11-24T21:54:54.117 回答