Sol2: call_constructor doesn't seem to work with factories for simple usertypes

Created on 18 Feb 2017  路  4Comments  路  Source: ThePhD/sol2

Using call_constructor with a factories instance when creating a simple usertype results in no matching function call takes this number of arguments and the specified types when trying to use the call constructor from Lua. This seems to be the case regardless of any other factors I tested (number of arguments to the factory function, the existence/non-existence of a "new" function, SOL_CHECK_ARGUMENTS/SOL_SAFE_USERTYPE defs, etc).

Note: Using call_constructor with factories works fine with regular usertypes (although there's currently no tests for the call_constructor/factories combo in the sol test cases).

Test code:

#define CATCH_CONFIG_MAIN
#define SOL_CHECK_ARGUMENTS
#include <catch.hpp>
#include <sol.hpp>

TEST_CASE("simple_usertype call_constructor with factories")
{
    struct FactoryTest {};

    sol::state lua;
    lua.open_libraries(sol::lib::base);

    auto factories = sol::factories([]() { return FactoryTest(); });

    lua.new_simple_usertype<FactoryTest>("FactoryTest",
        sol::meta_function::construct, factories,
        sol::call_constructor, factories
    );

    REQUIRE_NOTHROW(lua.script("a = FactoryTest.new()"));
    REQUIRE_NOTHROW(lua.script("b = FactoryTest()"));
}

Results:

-------------------------------------------------------------------------------
simple_usertype call_constructor with factories
-------------------------------------------------------------------------------
main.cpp(6)
...............................................................................

main.cpp(21): FAILED:
  REQUIRE_NOTHROW( lua.script("b = FactoryTest()") )
due to unexpected exception with message:
  lua: error: [string "b = FactoryTest()"]:1: sol: no matching function call
  takes this number of arguments and the specified types
Bug.On Fire

All 4 comments

Thanks for reporting. There are tests now for it and it's not fairly well-vetted. Try pulling from the latest or from:

https://github.com/ThePhD/sol2/releases/tag/v2.15.8

Appreciate the quick fix. The simple test I posted above works, but I am having a weird issue with my real use case. Will investigate it a bit more and post a new test case for you.

Okay, this test is rather convoluted and strangely constructed, but hopefully it's useful in tracking down what's going on. Basically, a table of userdata, when passed to a factory constructor is detected as a table of structs (using sol::object::is) when going through new but not when going through the call_constructor. Seems like it's probably just a weird symptom of something only tangentially related, but who knows.

#define CATCH_CONFIG_MAIN
#define SOL_CHECK_ARGUMENTS
#include <catch.hpp>
#include <sol.hpp>

TEST_CASE("simple_usertype call_constructor with a factory that takes a table of userdata")
{
    struct thing {};

    struct FactoryTest {};

    sol::state lua;
    lua.open_libraries(sol::lib::base);

    auto factories = sol::factories(
        [](const sol::table& tbl) {
            for (auto v : tbl)
            {
                REQUIRE(v.second.valid());

                // This fails only when the call_constructor is used:
                REQUIRE(v.second.is<thing>());
            }
            return FactoryTest();
        }
    );

    lua.new_simple_usertype<FactoryTest>("FactoryTest",
        sol::meta_function::construct, factories,
        sol::call_constructor, factories
    );

    lua.new_simple_usertype<thing>("thing");

    lua.script("things = {thing.new(), thing.new()}");

    // This succeeds:
    SECTION("new")
    {
        REQUIRE_NOTHROW(lua.script("a = FactoryTest.new(things)"));
    }

    // This fails:
    SECTION("call_constructor")
    {
        REQUIRE_NOTHROW(lua.script("b = FactoryTest(things)"));
    }
}

The result (omitted the atpanic error that results from REQUIRE failing during the lua.script call):

-------------------------------------------------------------------------------
simple_usertype call_constructor with a factory that takes a table of userdata
  call_constructor
-------------------------------------------------------------------------------
main.cpp(44)
...............................................................................

main.cpp(22): FAILED:
  REQUIRE( v.second.is<thing>() )
with expansion:
  false

This is now fixed, sorry about that: pull from the latest.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hmenke picture hmenke  路  6Comments

Moneyl picture Moneyl  路  10Comments

spin-scenario picture spin-scenario  路  8Comments

Koncord picture Koncord  路  4Comments

sagunkho picture sagunkho  路  4Comments