2009-11-24 96 views
1

当前我知道如何让C++对象实例化并在Lua中使用SWIG绑定传递,我需要的是相反的。用SWIG包装一个Lua对象以在C++中使用SWIG

我正在使用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) 

现在说我有一个名为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类,甚至可设置的函数签名是什么样子......

回答

1

我看起来从你的例子和讨论中得到的结论是,你期望Lua成为主要语言,而C++成为客户端。问题是,Lua C接口的设计不是这样工作的,Lua是客户端,所有的努力工作都是用C编写的,这样Lua可以毫不费力地称呼它。

现在,重要的问题是:为什么你不想有一个C对象的表示,并且倾向于在Lua中使用它?由于C++是一种低得多的语言,并且对象定义必须是静态的,并且Lua动态地定义了它的“对象”,所以让Lua适应C++对象要容易得多。

我看到的另一个问题是,你似乎在设计你的Lua代码在非常面向对象的方式。请记住,尽管Lua可以伪造面向对象的概念,但它不是作为面向对象的语言构建的,并且不应该主要用作一个。如果你想要一个完整的面向对象脚本语言,请使用python。

现在,如果你真的想以另一种方式做它,并认为其他的替代方案不适合你,那么我会建议,是你把Lua对象作为一个协程,这将允许您:

  • 保持对象 的表示在C++(在lua_State *)
  • 有相同的“对象类型”的多个单独的实例
  • Lua中需要清理的护理

但是,缺点是:

  • ,关于“对象”行动的所有功能 需要通过LUA API
  • 没有认识到不同的LUA类型(不容易/快速的方式这样做你 可以使用metatable)
  • 实现是相当繁琐的,很难decypher。

编辑: 这里是你如何可以在接口暴露在脚本的对象,每个对象实例将运行新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*/); 
} 
+0

在一个项目中,我可以在lua中移动很多东西,而不必用C++对象包装它们。我会失去一些灵活性,但我不能将必要的组件移入lua并重新获得我已经失去的一些东西 – 2009-12-30 18:48:07

+0

然而,我有其他项目没有这种奢侈品,例如我有一个RTS AI项目,打算在卢阿实施'小工具'或'插件'来扩展单位行为。因此,我需要能够将这个lua代码与该对象关联起来,所以会有表格填充了我需要与我的各种行为和任务类相关联的方法和代码,以及在我现有的基础结构中使用它们的工作 – 2009-12-30 18:50:20

+0

我会给你提问的,因为你提供了一个解决方案,虽然我很好奇你有什么更好的方法可以建议特别是AI情况 – 2009-12-30 18:51:38

0

你可以任何你想要的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方法,但它基本上是一样的。

+0

这并不能真正帮助我,因为我不想绑定C函数,我用C我工作++使用对象。此外,我不知道如何获得'pos'变量,如何实现IsAccount,或者如何实际使用'pos'表。 因此,我如何实际处理我的'Account'lua实例? – 2009-11-25 00:57:39

+0

从你最初的问题来看,你似乎正在用C++创建一个接口类,并尝试在Lua中创建这个接口的“子类”。你的问题表明,子类没有C++实现,只有Lua实现。您至少需要一个C接口来绑定Lua,您可以从Lua调用并将对象传递回您的C++应用程序。上面假设你使用SWIG来生成这个方法,它将C参数绑定到Lua堆栈位置(由pos指定)。挖掘SWIG Lua绑定实现;有很多你可以使用的。 – 2009-11-25 13:30:02

+0

当人们误解我想要的并假设我正在包装一个用于lua的C++对象时,我总是一次又一次地指向同一个文档,当时我实际上想要它。 – 2009-11-25 23:24:21

2

我不熟悉痛饮(我知道这是什么,但从来没有使用过),所以这可能不是你要找的答案。

我一直工作在C++项目,并使用luabind已经成功。它可以让你subclass C++ objects with Lua objects。您可能想尝试一下,看看它是否适合您。

+0

这看起来很有趣,我会仔细研究一下,你有没有关于通过luabind在lua中实现子类化性能的任何说明? – 2009-12-30 18:46:50

+0

我目前正在使用它来创建我正在处理的游戏中的所有“实体”。我还没有完成所有工作,但迄今为止,我一直对这个表现很满意。话虽如此,我并未处于测量性能过度的地步,所以很难说。我已经读过,使用Luabind和Lua C API确实存在开销,但在我的项目中,这不是问题。 – 2009-12-30 19:08:04