how to callback a lua function from a c function

后端 未结 2 831
孤街浪徒
孤街浪徒 2021-02-14 01:52

I have a C function (A) test_callback accepting a pointer to a function(B) as the parameter and A will \"callback\" B.

//typedef int(*data_callback         


        
相关标签:
2条回答
  • 2021-02-14 02:31

    The convenient way of doing calls to different Lua functions with different signatures:

    A. Make a class that will maintain Lua state safely and will provide easy interface. Do not write calls to Lua functions from scratch (with a lot of push/pop work and asserts) again and again - just use this class interface. This is safe, fast and convenient approach.

    B. Define push and pop methods to push/pop arguments on/from Lua stack:

    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. Define functions to call Lua functions:

    // 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. Set error handler (lua_pcall will call this Lua function if error)

    void setErrorHandler(const char * funcName)
    {
      lua_getfield (lua_state, LUA_GLOBALSINDEX, funcName);
      this->err_h = lua_gettop(lua_state);
    }
    
    0 讨论(0)
  • 2021-02-14 02:40

    I'm not sure I understand your question, if you are asking what would lua_test_callback look in C, it should be something like this

    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
    }
    

    You cannot just wrap test_callback, you need entirely different implementation to call Lua functions.

    (edit: changed lua_call to lua_pcall as suggested by Nick. I still omitted any error handling for brevity)

    0 讨论(0)
提交回复
热议问题