как отозвать функцию lua из функции c - PullRequest
11 голосов
/ 22 апреля 2010

У меня есть функция 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

Ответы [ 2 ]

9 голосов
/ 22 апреля 2010

Я не уверен, что понимаю ваш вопрос, если вы спрашиваете, что бы 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, как предложил Ник. Я все еще опускаю любую обработку ошибок для краткости)

3 голосов
/ 22 апреля 2010

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

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

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

template<typename T> void push(T argument);
template<typename T> void get(const int index, T& return_value);

template<> void State::push(bool arg)
{
  lua_pushboolean (lua_state, arg ? 1 : 0);
}

template<> void State::push(float arg)
{
  lua_pushnumber (lua_state, arg);
}

template<> void State::push(int arg)
{
  lua_pushnumber (lua_state, arg);
}

// ...
template<> void State::get(const int index, bool& ret)
{
      if (!lua_isboolean(lua_state, index)) { ... }
      ret = lua_toboolean(lua_state, index) != 0;
}

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

// Call function that takes 1 argument and returns nothing
template <typename A1>
void call(const char * funcName, A1 arg1)
{
  lua_getfield (lua_state, LUA_GLOBALSINDEX, funcName);       // push global function f on stack
  push (arg1);                                            // push first argument on stack
  assert_call(    lua_pcall(lua_state, 1, 0, this->err_h) );      // call function taking 1 argument and getting no return value
}


// call function that takes 2 argument and returns 1 value
template <typename R1, typename A1, typename A2>
void callr1(const char * funcName, R1& res, A1 arg1, A2 arg2)
{
  lua_getfield (lua_state, LUA_GLOBALSINDEX, funcName);       // push global function f on stack
  push (arg1);                                            // push first argument on stack
  push (arg2);
  assert_call(    lua_pcall(lua_state, 2, 1, this->err_h) );      // call function taking 2 arguments and getting 1 return value
  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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...