SWIG Lua: Расширение класса (%extension) с помощью%native. Можно ли добавить% нативный метод?

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

Я хочу иметь что-то вроде этого:

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

2 ответа

В файле.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, которую вы хотите использовать в качестве метода ваших пользовательских данных:

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

Я практически только что понял это, и я хотел опубликовать это здесь, потому что эта страница занимает высокие позиции в Google, и это довольно приличное решение для выполнения работы. Это должно быть сделано в каждом файле привязки оболочки (*.i), который вы пишете с помощью SWIG.

Удачи!

Lua не имеет какой-либо истинной концепции метода, только таблицы функций с некоторым синтаксическим сахаром, так что вы можете написать код Lua, который выглядит довольно OO'ish:

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

Когда ты пишешь

myInt = foo:Bar()

Луа на самом деле выполняет

myInt = foo.Bar(foo)

что заставит Lua искать в метатаблице foo функцию с именем 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, хотя я немного заржавел в этой области, вам, возможно, придется добавить Bar в метатаблицу Foo вместо этого или сделать это из C (см. Раздел 5.6 пользователя SWIG руководство по разделам.i файла, где вы можете попробовать это сделать).

Любопытно узнать, работает ли это.

Другие вопросы по тегам