1

I have this function signature I have to match

typedef int (*lua_CFunction) (lua_State *L);//target sig

Here's what I have so far:

    //somewhere else... 
    ...
registerFunction<LuaEngine>("testFunc", &LuaEngine::testFunc, this);
    ...

    //0 arg callback
void funcCallback0(boost::function<void ()> func, lua_State *state)
{
    func();
}

template<typename SelfType>
void registerFunction(const std::string &funcName, boost::function<void (SelfType*)> func, SelfType *self)
{
            //funcToCall has to match lua_CFunction
    boost::function<void (lua_State *)> funcToCall = boost::bind(&LuaEngine::funcCallback0, this,
        boost::bind(func, self), _1);
    lua_register(_luaState, funcName.c_str(), funcToCall);
}

However, at lua_register(_luaState..., it's still complaining about conversion issues

Error 1 error C2664: 'lua_pushcclosure' : cannot convert parameter 2 from 'boost::function' to 'lua_CFunction'

Anyone know how this can be solved?

Dustin Getz
  • 21,282
  • 15
  • 82
  • 131
jameszhao00
  • 7,213
  • 15
  • 62
  • 112
  • A more broad question that touches the same general problem of converting `boost::function` to plain C pointers: http://stackoverflow.com/questions/282372/demote-boostfunction-to-a-plain-function-pointer – Pavel Minaev Sep 12 '09 at 00:23

2 Answers2

4

This cannot be solved directly. Lua API wants a plain function pointers from you - that's just a code pointer, and nothing else. Meanwhile, boost::function is a function object, and there's no way it could possibly be convertible to a plain function pointer, because - roughly speaking - it captures not just the code, but also the state. In your example, the captured state is the value of self. So it has a code pointer for the code, and some data - and the target API expects just the code pointer.

Pavel Minaev
  • 99,783
  • 25
  • 219
  • 289
  • Please read the answer I just posted. My original suspicion was similar to yours (in that a func ptr can't capture state), but it turns out it can through some nice magic. – jameszhao00 Sep 12 '09 at 00:16
  • Nope, you're wrong. From the Boost docs (http://www.boost.org/doc/libs/1_37_0/doc/html/boost/function_base.html#id2623958-bb): "`template Functor* target();` - If this stores a target of type Functor, returns the address of the target. Otherwise, returns the NULL pointer." - and in your case, the result of `bind` will not store target of type `lua_CFunction`. There's no magic there (well, there's no magic in general). It is not possible to squeeze random 8 bytes into 4. – Pavel Minaev Sep 12 '09 at 00:21
1

The problem is that the compiler cant deduce the template parameter because there is an implicit conversion.

You need to store the function pointer into a function object.

function<int(lua_State *)> f = boost::bind(&LuaEngine::testFunc, this)
registerFunction<LuaEngine>("testFunc", f);

And your function expects a void return type and that is needed to change to int too.

leiz
  • 3,984
  • 2
  • 23
  • 17