LuaBridge icon indicating copy to clipboard operation
LuaBridge copied to clipboard

addCFunction in 3rd party class

Open Mellnik opened this issue 2 years ago • 6 comments

This library is just awesome but it seems that I'm overseeing something on this simple problem.

I have a class from a third party library which cannot be modified at all. I'm exposing this class with the usual beginClass. Now I'd like to use addCFunction on this class but I cannot do that because it only accepts class member functions. std::function also doesn't work here.

.addCFunction("MyCustomFunc", std::function<int(lua_State*)>([](lua_State* L) {
    luabridge::push(L, 1337);
    luabridge::push(L, 3.1415);
    return 2;
}))

How can I add a C function with lua_State and custom return values to my class which cannot be modified?

Thank you!

Mellnik avatar Jun 02 '22 12:06 Mellnik

If you use addCFunction, you need to make sure you provide a lua_CFunction:

int myCFunction(lua_State*) { return 0; }

.addCFunction("MyCustomFunc", &myCFunction))

or eventually decay a lambda to a function pointer

.addCFunction("MyCustomFunc", +[](lua_State*) -> int { return 0; })

kunitoki avatar Jun 16 '22 05:06 kunitoki

Your first suggestion does not work. Because the class on which I want to do addCFunction cannot be modified. It's a 3rd party class. So when I do what you wrote it gives an error.

cannot convert argument 2 from 'int (__cdecl *)(lua_State *)' to 'int (__cdecl NameOfThe3dPartyClass::* )(lua_State *)'

The second suggestion with the lambda does not work as well for the same reason.

What luabridge is missing here is a specialization for addCFunction where the bound function is not part of the class. Pretty much a "function member proxy" like for normal non-CFunctions as described here. http://vinniefalco.github.io/LuaBridge/Manual.html#s2.5

Mellnik avatar Jun 16 '22 14:06 Mellnik

You are right, i thought this was also in vanilla luabridge, but this is only possible with luabridge3. can't you use a normal function ?

.addFunction("MyCustomFunc", +[](MyClass* self, lua_State* L) { })

In luabridge3, addCfunction disappeared and i added support for generic CFunction with self object on top of the stack, see https://github.com/kunitoki/LuaBridge3/blob/master/Source/LuaBridge/detail/Namespace.h#L978-L998

An example usage:

struct MyClass {};

int cFunctionMethod(lua_State* L)
{
    auto ref = luabridge::LuaRef::fromStack(L, 1);
    if (!ref.isUserdata() || !ref.isInstance<MyClass>()) {
        return 0;
    }
    
    auto arg = luabridge::LuaRef::fromStack(L, 2);
    if (!arg.isNumber()) {
        return 0;
    }
    
    std::error_code ec;
    luabridge::push(L, arg.cast<int>() + 1000, ec);

    return 1;
}

luabridge::getGlobalNamespace(L)
    .beginClass<MyClass>("MyClass")
        .addFunction("method", &cFunctionMethod)
    .endClass();

runLua("result = MyClass():method(1000)");
ASSERT_EQ(2000, result<int>());

kunitoki avatar Jun 16 '22 19:06 kunitoki

@kunitoki Nice, is it possible to use that piece of code in the "official" luabridge?

Mellnik avatar Jun 27 '22 20:06 Mellnik

Yeah, not pretty but you can "hack it" somehow registering a static function to your class with addStaticFunction but call it with : instead of .

kunitoki avatar Jun 27 '22 22:06 kunitoki

Ok, let me implement this :)

dmitry-t avatar Aug 08 '22 19:08 dmitry-t