Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

addCFunction in 3rd party class #285

Open
Mellnik opened this issue Jun 2, 2022 · 6 comments
Open

addCFunction in 3rd party class #285

Mellnik opened this issue Jun 2, 2022 · 6 comments

Comments

@Mellnik
Copy link

Mellnik commented Jun 2, 2022

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!

@kunitoki
Copy link

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; })

@Mellnik
Copy link
Author

Mellnik commented Jun 16, 2022

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

@kunitoki
Copy link

kunitoki commented Jun 16, 2022

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>());

@Mellnik
Copy link
Author

Mellnik commented Jun 27, 2022

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

@kunitoki
Copy link

kunitoki commented Jun 27, 2022

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

@dmitry-t
Copy link
Collaborator

dmitry-t commented Aug 8, 2022

Ok, let me implement this :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants