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

Question: Is there a C++ way to query the metatable of a sol::protected_function? #1650

Open
joergbrech opened this issue Nov 21, 2024 · 0 comments

Comments

@joergbrech
Copy link

joergbrech commented Nov 21, 2024

Thanks a lot for this amazing library!

With sol2, you can query the metatable of tables and table proxys using my_table[sol::metatable_key]. Is there any way to query the metatable of a sol::protected_function directly using the sol API? It doesn't implement operator[] and I found no way to convert it to a table or proxy type. A generic function like sol::getmetatable would be cool.

My use case is that I want to attach metadata to my C++ functions like so:

template <typename Table, typename Key, typename T>
void add_metadata(sol::state_view& lua, Table&& t, Key&& key, T&& value)
{
    if (!t[sol::metatable_key].valid()) {
        sol::table func_meta = lua.create_table();
        t[sol::metatable_key] = func_meta;
    }
    t[sol::metatable_key][std::forward<Key>(key)] = std::forward<T>(value);
}

int main()
{
    sol::state lua;
    lua.open_libraries(sol::lib::base);

    auto g = lua.globals();
    lua.set_function("bar", [](){});
    add_metadata(lua, g["bar"], "foo", "baz");
    
    foobar(lua, g["bar"]); // see below

    return 0;
}

Now I want to query this metadata in a context (function body of foobar), where I don't have g["bar"], but rather a sol::protected_function. I managed to retrieve the metatable with sol::state::script and one line of LUA code, but it would be nice to have something in the C++ API (which might boost performance as well?):

template <typename Table, typename Key>
auto get_metadata(sol::state_view& lua, Table&& t, Key&& key)
{
    // This works, but I was hoping for a cleaner solution
    lua["_tmp"] = t;
    lua.script(R"(
        _tmp = getmetatable(_tmp)
    )");
    sol::object ret = lua["_tmp"][std::forward<Key>(key)];
    return ret;
}

void foobar(sol::state_view& lua, sol::protected_function const& f)
{
    // in this context, I don't have access to f as a  proxy or table
    std::cout << get_metadata(lua, f, "foo").as<std::string>() << "\n";
}

Run this on godbolt

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

1 participant