Lua обратный вызов из C ++

0

У меня есть хост c++, в котором я использую tolua++, чтобы выставить некоторые классы в Lua. Один из классов имеет функцию, которая должна зарегистрировать обратный вызов из lua. Поэтому, когда код c++ требует вызова Lua-зарегистрированной функции, он может. Однако функция является функцией таблицы/класса. Я сделал это раньше с именем функции строки (не частью класса "lua") с успехом, но мне любопытно, могу ли я каким-то образом сохранить функцию Lua, а не имя функции.

Я определяю свои классы lua как:

MyClass = {}

function MyClass:Create()
    local obj = {}

    -- copy all functions from MyClass table to this local obj and return it
    local k,v
    for k,v in pairs(obj) do
        obj[k] = v
    end

    return obj
end

function MyClass:Enter()
    self.CPlusClass = CPlusClass:Create()   -- this is the C++ class creation, I defined a static function Create()
    self.CPlusClass:RegisterCallback(15, self.Callback) -- this is where I want to pass this instances function to be called back from the C++ class
end

function MyClass:Callback(reader)
    -- I want to be able to use self here as well so it needs to be the same instance
end

Внутри MyClass: Enter() - это то, где я хочу зарегистрировать функцию "класс" Lua MyClass :: Callback, чтобы иметь возможность вызываться из объекта c++. Как передать это в функцию c++? Что бы тип был так, чтобы он вызывал MyClass: Callback() из c++, также передавая "self", чтобы он был тем же "экземпляром" класса?

Поэтому я знаю, что "я" ссылается на фактическую переменную, которую я создал, и я предполагаю, что она будет в глобальной таблице по имени переменной, но когда вы находитесь в классе "lua", как я могу определить, что означает имя переменной "я" слишком? Если бы я мог получить это, я мог бы передать это моей функции c++ и сохранить ее как строку, чтобы я мог вызвать getglobal на нее, чтобы получить эту конкретную таблицу, а затем я мог бы передать имя функции таблицы как строку и в [ CN10] Я мог бы получить это и назвать его. Но вопрос в том, как я могу преобразовать "я" в фактическое имя переменной, которое он указывает, чтобы я мог вызвать getglobal в c++, чтобы получить эту таблицу?

  • 0
    self - не глобальная переменная, self - автоматическая переменная, определяемая table:function синтаксический сахар. function table:class(args...) ... end идентична function table.class(self, args...) ... end . Аналогичным образом вызов tab:class(args...) идентичен tab.class(tab, args...) (хотя tab оценивается только один раз).
  • 0
    Я это понимаю. Однако self ссылается на таблицу, которую я создал где-то в моей программе lua. Как я могу сказать, на какое имя переменной ссылается self?
Показать ещё 12 комментариев
Теги:
lua

2 ответа

2
Лучший ответ

Если вы хотите сохранить подпись и операцию RegisterCallback (в отличие от того, чтобы усилить ее для понимания обратных вызовов метода объекта каким-то образом), вам необходимо создать закрытие и передать это как обратный вызов. Что-то вроде этого:

function create_closure(obj, fun)
    return function(...)
        return obj[fun](...)
    end
end

а также

function MyClass:Enter()
    self.CPlusClass = CPlusClass:Create()   -- this is the C++ class creation, I defined a static function Create()
    self.CPlusClass:RegisterCallback(15, create_closure(self, "Callback"))
end
  • 0
    Мой второй параметр RegisterCallback () был на самом деле строкой. Моя первоначальная надежда состояла в том, чтобы иметь возможность получить имя переменной, на которую ссылается self, и сопоставить ее как «obj: Callback», а затем разбить ее в функции C ++. Каким должен быть второй параметр, если я сделаю этот метод?
  • 0
    RegisterCallback принимает строку? Предполагается, что имена глобальной функции, которая может быть найдена позже?
Показать ещё 10 комментариев
3

Вы экспортировали класс CPlusClass из C++ в Lua: этот класс C++ имеет RegisterCallback, который принимает указатель на функцию или экземпляр YourCallbackClass, который использует виртуальные методы для отправки на правильный объект. Тогда вам нужно только экспортировать YourCallbackClass в Lua: за кулисами, версия Lua создаст экземпляр и передаст его вашему C++ RegisterCallback. Например:

class CPlusClass {
public: 
    RegisterCallback(int val, CPlusCallback* cb) { ... store cb for later... }
};

class SomeObj; // type of Objects that you want to call back into

class CPlusCallback {
public:
    typedef void (SomeObj::*Method)();
    CPlusCallback(SomeObj* obj, Method method) { callee=obj; method=method; }
    call() { callee->*Method(); }
private:
    SomeObj* callee; 
    Method method;
};

Ваш CPlusCallback, скорее всего, другой, это всего лишь пример. Например, если вы просто хотите, чтобы функции не были методами, вам не нужно хранить вызываемого абонента. Если вы хотите оба, то CPlusCallback должен быть базовым классом, а вызов() является виртуальным, а производные классы реализуют детали по мере необходимости. Приспосабливайтесь к вашей ситуации.

Затем экспортируйте CPlusCallback и SomeObj в Lua, затем вы можете сделать в Lua:

somObj = SomeObj:Create()

function MyClass:Enter()
    -- creates Lua instance of CPlusClass, with a user data for the C++
    -- counterpart as member
    self.CPlusClass = CPlusClass:Create()  
    self.CPlusCallback = CPlusCallback:Create(someObj, someObj.method)
    self.CPlusClass:RegisterCallback(15, self.CPlusCallback)
end

где вышеприведенное предполагает, что someObj.method - это метод, который вы экспортировали, из класса C++ SomeObj с правильной сигнатурой void (SomeObj :: * Method)().

  • 0
    Спасибо за альтернативный метод. В настоящее время я получил метод отправки self, затем строковое имя метода класса lua и его обратный вызов из C ++. Очень похоже на то, что вы сделали здесь. Меня интересовали детали того, как это делается, но я понял это.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню