2

I'm trying to return an instance of a C++ class and return it to Python using Boost.Python. What I'd like to do is have code like:

class foo {
    std::string name;
    public:
    void set_name(std::string name) {this->name = name;}
    std::string get_name() {return this->name;}
};
class bar {
    public:
    foo get_foo(std::string name) {
        foo my_foo;
        my_foo.set_name(name);
        return my_foo;
    }
};

and I'm wrapping it with:

BOOST_PYTHON_MODULE(foobar)
{
    class_<foo, boost::noncopyable>("foo")
    .def("set_name", &foo::set_name)
    .def("get_name", &foo::get_name)
;

    class_<bar, boost::noncopyable>("bar")
    .def("get_foo", &bar::get_foo);
 }

As you might have also noticed, I need both foo and bar to be noncopyable because in the real project, there are sockets inside. When trying to compile the above, I get a Python TypeError:

TypeError: No to_python (by-value) converter found for C++ type

I'm calling it with Python like this:

Python 3.6.1 (default, Mar 22 2017, 06:17:05) 
[GCC 6.3.0 20170321] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import foobar
>>> a=foobar.bar()
>>> b=a.get_foo("myname")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: No to_python (by-value) converter found for C++ type: foo
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 63, in apport_excepthook
    from apport.fileutils import likely_packaged, get_recent_crashes
  File "/usr/lib/python3/dist-packages/apport/__init__.py", line 5, in <module>
    from apport.report import Report
  File "/usr/lib/python3/dist-packages/apport/report.py", line 30, in <module>
    import apport.fileutils
  File "/usr/lib/python3/dist-packages/apport/fileutils.py", line 23, in <module>
    from apport.packaging_impl import impl as packaging
  File "/usr/lib/python3/dist-packages/apport/packaging_impl.py", line 24, in <module>
    import apt
  File "/usr/lib/python3/dist-packages/apt/__init__.py", line 23, in <module>
    import apt_pkg
ModuleNotFoundError: No module named 'apt_pkg'

Original exception was:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: No to_python (by-value) converter found for C++ type: foo
>>> 

1 Answer 1

5

I've found a way to make the code work. It seems I should use a pointer return type and boost::python::return_value_policy<boost::python::manage_new_object>().

#include <boost/python.hpp>
class foo {
    std::string name;
    public:
    void set_name(std::string name) {this->name = name;}
    std::string get_name() {return this->name;}
};
class bar {
    public:
    foo* get_foo(std::string name) {
        foo* my_foo = new foo();
        my_foo->set_name(name);
        return my_foo;
    }
};
BOOST_PYTHON_MODULE(foobar)
{
    boost::python::class_<foo, boost::noncopyable>("foo")
    .def("set_name", &foo::set_name)
    .def("get_name", &foo::get_name)
;

    boost::python::class_<bar, boost::noncopyable>("bar")
    .def("get_foo", &bar::get_foo, boost::python::return_value_policy<boost::python::manage_new_object>());

 }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.