SWIG Lua:使用%native扩展(%extend)类。是否可以添加%native方法?

时间:2013-05-03 13:24:25

标签: c++ lua swig

%module test
class Foo{
public:
  Foo(); 
}

我希望有这样的东西:

%extend Foo{
%native(Bar) int Bar(lua_State * L);
}

2 个答案:

答案 0 :(得分:1)

在绑定的.i文件中,最后包含以下代码:

%wrapper %{
// This is code to add a new function to the object's metatable
void script_addNativeMethod(lua_State *L, const char *className, const char *methodName, lua_CFunction fn)
{
    SWIG_Lua_get_class_registry(L); /* get the registry */
    lua_pushstring(L, className);   /* get the name */
    lua_rawget(L,-2);               /* get the metatable itself */
    lua_remove(L,-2);               /* tidy up (remove registry) */

    // If the metatable is not null, add the method to the ".fn" table
    if(lua_isnil(L, -1) != 1)
    {
        SWIG_Lua_get_table(L, ".fn");
        SWIG_Lua_add_function(L, methodName, fn);
        lua_pop(L, 2);              /* tidy up (remove metatable and ".fn" table) */
    }
    else
    {
        printf("[script_addNativeMethod(..)] - \"%s\" metatable is not found. Method \"%s\" will not be added\n", className, methodName);
        return;
    }
}
%}

这样做是为包装CPP文件添加一个名为" script_addNativeMethod"的新函数。您可以在" init"中调用此函数。像这样绑定代码:

// Wrapper to add native Lua methods to existing C++ classes
%init %{
    script_addNativeMethod(L, "MetatableName", "methodName", /*int function(lua_State *L)*/function);
%}

最重要的是,在绑定文件中,您需要使用实际的本机lua函数作为userdata的方法:

%{
int function(lua_State *L)
{
    printf("Method called!\n");
    return 0;
}
%}

我几乎只是想出来了,我想在这里发布,因为这个页面在谷歌中排名很高,这是一个非常不错的解决方案来完成工作。这需要在您使用SWIG编写的每个包装器绑定(* .i)文件中完成。

祝你好运!

答案 1 :(得分:0)

Lua没有任何真正的方法概念,只有具有一些语法糖的函数表,所以你可以编写看起来很OO'ish的Lua代码:

foo = test.Foo() # will call the C++ Foo constructor and return a wrapped (Lua) Foo
myInt = foo:Bar()

写作时

myInt = foo:Bar()

Lua实际上正在执行

myInt = foo.Bar(foo)

这将导致Lua在foo metatable中查找名为Bar的函数,并将foo实例作为第一个参数。因此,您需要做的更多的是以下伪代码(未经测试,可能存在语法错误,参数顺序错误等等,但希望您能得到这个想法):

%native(Bar) int Bar(lua_State * L);

%{
int Bar(lua_State*L) {
  // there should be one arg on the stack: the Foo instance
  Foo* foo = (Foo*)<get void* from L stack>
  int answer = foo.Bar();
  // push answer onto L stack
  lua_pushnumber(L, answer);
  return 1;
}
%}

%luacode {
  test.Foo.Bar = test.Bar
}
...
%}

%luacode使得Bar可以作为Foo“class”的一部分使用,虽然我在那个区域有点生疏,你可能不得不将Bar添加到Foo metatable中,或者从C中添加它(参见5.6节)用于.i文件部分的SWIG用户指南,您可以尝试执行此操作)。

很想知道这是否有效。