包装一个Lua对象以在带有SWIG的C ++中使用 [英] Wrapping a Lua object for use in C++ with SWIG

查看:117
本文介绍了包装一个Lua对象以在带有SWIG的C ++中使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Currently I know how to have C++ objects instantiated and passed around in Lua using SWIG bindings, what I need is the reverse.

我正在使用Lua& C ++和SWIG.

I am using Lua & C++ & SWIG.

我在C ++中具有接口,在lua中具有对象,这些接口实现的方法可以完成相同的工作并具有相同的结构.我希望能够在lua中实例化这些对象,然后使用指向它们相似的接口的指针在C ++中传递它们.

I have interfaces in C++ and objects in lua, that implement methods which do the same job and have the same structure. I would like to be able to instantiate these objects in lua yet pass them around in C++ using pointers to that interface which they resemble.

这样,我可以想象创建一个接口的c ++实现,该接口将充当所述lua对象的处理程序,但我不知道该怎么做.该类将充当C ++世界中lua对象的代表或代理.

As such I can imagine creating a c++ implementation of the interface which would act as a handler for said lua object, yet I don't know how to do this. The class would act as the lua objects representative or proxy in the C++ world.

为澄清起见,我将从以下示例代码开始,该代码用于回答我提出的类似问题:

To clarify I shall start with the following example code used in an answer to a similar question I asked:

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 ++中有一个叫做Bank的类:

Now say that I have a class in C++ called Bank:

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

我想在lua中执行以下操作的机制:

What I would like here is a mechanism for doing the following in lua:

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

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

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

If I need to take an extra step such as instantiating a C++ class to act as a proxy and pass it the lua table with all my lua functions etc, I can imagine it looking like this:

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的功能签名是什么...

The problem here being I have no idea how I would implement the ProxyAccount class, or even what the function signature of settable would look like...

推荐答案

我似乎从您的示例和讨论中得到的是,您期望Lua是主要语言,而C ++是客户端.问题是,Lua C接口的设计不像那样工作,Lua应该是客户端,而所有辛苦的工作都应该用C编写,以便Lua可以毫不费力地调用它.

What I seem to gather from your examples and the discussions is that you are expecting Lua to be the primary language, and C++ to be the client. The problem is, that the Lua C interface is not designed to work like that, Lua is meant to be the client, and all the hard work is meant to be written in C so that Lua can call it effortlessly.

现在,重要的问题是:为什么不想要对象的C表示,而更喜欢在Lua中使用它呢?由于C ++是一种底层语言,并且对象定义必须是静态的,并且Lua动态定义其对象",因此使Lua适应C ++对象要容易得多.

Now, the important question is: why don't you want to have a C representation of the object, and prefer to have it in Lua? Since C++ is a much lower level language, and object definitions must be static, and Lua dynamically defines its "objects" it is much easier to have Lua adapt to C++ objects.

我看到的另一个问题是,您似乎正在以非常面向对象的方式设计Lua代码.请记住,即使Lua可以伪造面向对象的概念,但它并不是作为面向对象的语言构建的,因此不应主要用作一种语言.如果要使用完整的OO脚本语言,请改用python.

Another issue I see is that you seem to be designing your Lua code in a very Object Oriented manner. Remember that even though Lua can fake Object Oriented concepts, it is not built as an Object Oriented language, and should not be used primarily as one. If you want a fully OO scripting language, use python instead.

现在,如果您真的想要以其他方式进行操作,并且认为其他替代方法对您不起作用,那么我建议您将Lua对象保留为协程,这将使您能够:

Now if you Really want to do it the other way, and considered that the other alternatives do not work for you, then what I would recommend, is that you keep the Lua object as a coroutine, this will allow you to:

  • 保留对象的表示形式 在C ++中(lua_State *)
  • 具有相同对象类型"的多个单独实例
  • Lua负责清理
  • Keep a representation of the object in C++ (the lua_State *)
  • Have multiple individual instances of the same "object type"
  • Lua takes care of the cleanup

但是,缺点是:

  • 作用于对象"的所有功能 需要通过lua API做到这一点
  • 没有简单/快速的方法来识别不同的lua类型(您 可以使用一个元表)
  • 实施非常麻烦,而且难以解密.
  • All functions that act on an "object" need to do so through the lua API
  • There is no easy/fast way to recognize different lua types (you could use a metatable)
  • Implementation is quite cumbersome, and hard to decypher.

这是在脚本中将接口公开给对象的方法,每个对象实例将运行一个新的lua_State,并分别运行其脚本,从而使对象成员数据"成为脚本实例内部的全局变量.为对象的方法实现API的过程如下:

Here is how you could expose the interface to an object in a script, Each object instance would be running a new lua_State, and run its script individually, thus allowing for your "Object member data" to just be globals inside the script instance. Implementing the API for the object's methods would go like this:

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

这篇关于包装一个Lua对象以在带有SWIG的C ++中使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆