使用Lua + SWIG将成员动态添加到类 [英] Add members dynamically to a class using Lua + SWIG

查看:154
本文介绍了使用Lua + SWIG将成员动态添加到类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个Lua代码,创建一个表并动态添加一个新成员。运行这个我可以得到hello在屏幕上如预期:

This Lua code, creates a table and dynamically adds a new member. Running this I can get "hello" on the screen as expected:

foo = {}
foo.x = "hello"
print(foo.x)

但现在我使用SWIG绑定一些C ++类到Lua。
为此,在 test.i (SWIG模块文件)中创建了一个类似这样的简单类:

But now I'm using SWIG to bind some C++ classes to Lua. For that purpose, in a test.i (SWIG module file) I created a simple class like this:

%module test

%inline
%{

class Foo
{
public:
  Foo() { X = 0; }
  void SetX(int x) { X = x; }
  int GetX() { return X; }
private:
  int X;
};

%}

然后我写了一个测试Lua代码: / p>

Then I wrote a test Lua code like that:

obj = test.Foo()
obj:SetX(5)
print("Number: " .. obj:GetX())

运行并获取Number 5 。问题是,当我动态添加一个新成员到我的SWIG绑定对象,我尝试访问它,像这样:

Running and getting "Number 5" as expected. The problem is that when I dynamically add a new member to my SWIG-binded object, and I try to access it, like so:

obj.Y = 7
print("Number: " .. obj.Y)

我收到此错误消息:

"attempt to concatenate field 'Y' (a nil value)"

是否可以在使用SWIG绑定的对象上动态添加新成员?是否有一些选项,而不必移动到另一个Lua绑定库?

Is it possible to dynamically add new members on objects binded using SWIG? Is there some option without having to move to another Lua binding library?

推荐答案

SWIG不为其对象使用表;它使用 userdata 。毕竟,这些对象是C ++对象,需要存储Lua代码不应该触摸的C ++数据。

SWIG doesn't use tables for its objects; it uses userdata. After all, those objects are C++ objects, and need to store C++ data that Lua code shouldn't be able to touch.

我不会费心寻找另一个Lua结合库;几乎所有的 都使用userdata,Lua代码显然不能修改(为了提供能够做到这一点)。

And I wouldn't bother looking for "another Lua binding library"; pretty much all of them use userdata, which Lua code explicitly cannot modify (in order to provide the ability to do exactly this).

,这并不意味着你不能欺骗。

However, that doesn't mean you can't cheat.

你可以随时将你从C ++代码中获得的对象包装到你自己的Lua表中,这将有一个metatable,转发未知的调用到C ++对象。这样做的代码看起来像这样:

You can always wrap the object you get from C++ code into your own Lua table, which would have a metatable that forwards unknown calls to the C++ object. The code to do so would look something like this:

local function WrapObject(cppObject)

    local proxy = {}

    local wrapper_metatable = {}

function wrapper_metatable.__index(self, key)
    local ret = rawget(self, key)
    if(not ret) then
        ret = cppObject[key]
        if(type(ret) == "function") then
            return function(self, ...)
                return ret(cppObject, ...)
            end
        else
            return ret
        end
    else
        return ret
    end

end


    setmetatable(proxy, wrapper_metatable)
    return proxy
end

返回的代理对象是一个Lua表,可以设置键和值。当你得到一个值,例如调用一个函数,它将看到该值是否在表中设置。如果没有,它会尝试从你包装的C ++对象中获取它,这将通过它的元表。

The returned proxy object is a Lua table that can have keys and values set on it. When you get a value, such as to call a function, it will see if that value was set in the table. If not, it attempts to fetch it from the C++ object that you wrapped, which will go through its metatable.

如果你的C ++类使用 __ add __ sub __ tostring 等。

You'll need to expand this metatable if your C++ class uses other metafunctions like __add, __sub, __tostring and so forth.

这篇关于使用Lua + SWIG将成员动态添加到类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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