как к обратному вызову lua функционируют от функции c

У меня есть функция C (A) test_callback при принятии указателя на функцию (B), поскольку параметр и A будут "обратный вызов" B.

//typedef int(*data_callback_t)(int i);
int test_callback(data_callback_t f)
{
    f(3);   
}


int datacallback(int a )
{
    printf("called back %d\n",a);
    return 0;
}


//example 
test_callback(datacallback); // print : called back 3 

Теперь, я хочу перенестись test_callback так, чтобы их можно было назвать от lua, предположить, что имя lua_test_callback ; и также входной параметр к нему был бы функцией lua. Как я должен достигнуть этой цели?

function lua_datacallback (a )
    print "hey , this is callback in lua" ..a
end


lua_test_callback(lua_datacallback)  //expect to get "hey this is callback in lua 3 "

Править:

Эта ссылка позволяет хранить функцию обратного вызова для более позднего использования.

//save function for later use 
callback_function = luaL_ref(L,LUA_REGISTRYINDEX);


//retrive function and call it 
lua_rawgeti(L,LUA_REGISTRYINDEX,callback_function);
//push the parameters and call it
lua_pushnumber(L, 5); // push first argument to the function
lua_pcall(L, 1, 0, 0); // call a function with one argument and no return values

11
задан Community 23 May 2017 в 12:34
поделиться

2 ответа

Я не уверен, что понимаю ваш вопрос, если вы спрашиваете, что бы lua_test_callback посмотрите на C, это должно быть примерно так

int lua_test_callback(lua_State* lua)
{
    if (lua_gettop(lua) == 1 && // make sure exactly one argument is passed
       lua_isfunction(lua, -1)) // and that argument (which is on top of the stack) is a function
    {
        lua_pushnumber(lua, 3); // push first argument to the function
        lua_pcall(lua, 1, 0, 0); // call a function with one argument and no return values
    }
    return 0; // no values are returned from this function
}

Вы не можете просто обернуть test_callback , вам нужна совершенно другая реализация для вызова функций Lua.

(правка: изменен lua_call на lua_pcall , как было предложено Ником. Я все еще опускал обработку ошибок для краткости)

9
ответ дан 3 December 2019 в 08:54
поделиться

Удобный способ выполнения вызовов разных функций Lua с разными сигнатурами:

A. Создайте класс, который будет безопасно поддерживать состояние Lua и будет обеспечивать простой интерфейс. Не пишите вызовы функций Lua с нуля (с большим количеством операций push / pop и утверждений) снова и снова - просто используйте этот интерфейс класса. Это безопасный, быстрый и удобный подход.

Б. Определите методы push и pop для отправки / извлечения аргументов в / из стека Lua:

 template  void push (T argument); 
template  void get (const int index, T & return_value ); 
 
template <> void State :: push (bool arg) 
 {
lua_pushboolean (lua_state, arg? 1: 0); {{1} }} 
 
template <> void State :: push (float arg) 
 {
lua_pushnumber (lua_state, arg); 
} {{ 1}} 
template <> void State :: push (int arg) 
 {
lua_pushnumber (lua_state, arg); 
} 
 { {1}} // ... 
шаблон <> void State :: get (const int index, bool & ret) 
 {
if (! Lua_isboolean (lua_state, index) ) {...} 
ret = lua_toboolean (lua_state, index)! = 0; 
} 
 

C.Определите функции для вызова функций Lua:

 // Вызов функции, которая принимает 1 аргумент и ничего не возвращает 
template  
void call (const char * funcName, A1 arg1) {{1 }} {
lua_getfield (lua_state, LUA_GLOBALSINDEX, funcName); // помещаем глобальную функцию f в стек 
push (arg1); // помещаем первый аргумент в стек 
assert_call (lua_pcall (lua_state, 1, 0, this-> err_h)); // вызываем функцию с 1 аргументом и не получаем возвращаемого значения 
} 
 
 
 // вызываем функцию, которая принимает 2 аргумента и возвращает 1 значение 
template  
void callr1 (const char * funcName, R1 & res, A1 arg1, A2 arg2) 
 
lua_getfield (lua_state, LUA_GLOBALSINDEX, funcName); // помещаем глобальную функцию f в стек 
push (arg1); // помещаем первый аргумент в стек 
push (arg2); 
assert_call (lua_pcall (lua_state, 2, 1, this-> err_h)); // вызываем функцию, принимающую 2 аргумента и получающую 1 возвращаемое значение 
get (-1, res); 
lua_pop (lua_state, 1); 
} 
 

D. Установить обработчик ошибок (lua_pcall вызовет эту функцию Lua в случае ошибки)

 void setErrorHandler (const char * funcName) 
 {
lua_getfield (lua_state, LUA_GLOBALSINDEX, funcName); 
this -> err_h = lua_gettop (lua_state); 
 
 
4
ответ дан 3 December 2019 в 08:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: