I am trying to bind a C++ class with a private constructor using Boost.Python.
Let assume that I have the following class:
class Test
{
public:
static Test& GetInstance()
{
static Test globalInstance;
return globalInstance;
}
int content(){return 0;}
private:
Test(){std::cout << "Object constructed" << std::endl;}
};
This class has a private constructor and to get an instance of the class, we must call the GetInstance()
method.
I tried to bind it, using the following code:
BOOST_PYTHON_MODULE(test)
{
class_<Test>("Test", no_init)
.def("create", &Test::GetInstance)
.def("content", &Test::content);
}
This code does not compile and gives me two errors:
/Sources/Boost/boost/python/detail/invoke.hpp:75:12: error: type 'const boost::python::detail::specify_a_return_value_policy_to_wrap_functions_returning<Test &>' does not provide a call operator
/Sources/Boost/boost/python/detail/caller.hpp:102:98: error: no member named 'get_pytype' in 'boost::python::detail::specify_a_return_value_policy_to_wrap_functions_returning<Test &>'
However, if I create a function, which calls GetInstance()
, like the following:
Test create()
{
return Test::GetInstance();
}
and that I replace .def("create", &Test::GetInstance)
by .def("create", create)
in my binding, everything works fine.
Why can't I use the public GetInstance()
method directly?
The problem here actually comes from the lack of explicit return policy. If a function/method does not return by value, we must set its return policy to one of:
reference_existing_object
copy_non_const_reference
copy_const_reference
manage_new_object
return_by_value
So, simply binding the GetInstance()
method like so:
.def("create", &Test::GetInstance, return_value_policy<copy_non_const_reference>())
solves the issue.
Hope it can help someone, as the error messages from Boost don't help that much here…