Opened 11 years ago

Closed 11 years ago

Last modified 11 years ago

#6203 closed Bugs (invalid)

boost::python::api::object constructor failure

Reported by: Johan Råde <johan.rade@…> Owned by: Ralf W. Grosse-Kunstleve
Milestone: To Be Determined Component: python USE GITHUB
Version: Boost 1.48.0 Severity: Problem
Keywords: Cc:

Description

Here is the C++ code for a Python extension module and a Python script that calls the module. Expected behavior when you run the script:

The script runs and produces the output "Hello, I'm Y!"

Observed behavior (with Boost 1.48.0, Python 2.7.2, MSVS 2010):

The script fails with the error message:

Traceback (most recent call last):
  File "../TestHello/TestHello.py", line 12, in <module>
    y = Hello.create('Y')
TypeError: No to_python (by-value) converter found for C++ type: class Y
Press any key to continue . . .

I have also attached a zip file with the code as a solution for MSVS 2010 and Python Tools for Visual Studio.

Hello.cpp:

#include <string>
#include <exception>
#include <boost/noncopyable.hpp>
#include <boost/python.hpp>

using std::string;
using boost::noncopyable;
using boost::python::class_;
using boost::python::def;

class X : noncopyable {
public:
    string hello() const { return "Hello, I'm X!"; }
};

class Y : noncopyable {
public:
    string hello() const { return "Hello, I'm Y!"; }
};

class Z : noncopyable {
public:
    string hello() const { return "Hello, I'm Z!"; }
};

PyObject* create(char c)
{
    if(c == 'X')
        return boost::python::api::object(new X).ptr();
    else if(c == 'Y')
        return boost::python::api::object(new Y).ptr();
    else if(c == 'Z')
        return boost::python::api::object(new Z).ptr();
    else
        throw std::exception("The function argument must be 'X', 'Y' or 'Z'.");
}

BOOST_PYTHON_MODULE(Hello)
{
    class_<X, noncopyable>("X").def("hello", &X::hello);
    class_<Y, noncopyable>("Y").def("hello", &Y::hello);
    class_<Z, noncopyable>("Z").def("hello", &Z::hello);

    def("create", &create);
}

Test.py:

import Hello
y = Hello.create('Y')
print(y.hello())

Attachments (1)

Test.zip (11.1 KB ) - added by Johan Råde <johan.rade@…> 11 years ago.

Download all attachments as: .zip

Change History (4)

by Johan Råde <johan.rade@…>, 11 years ago

Attachment: Test.zip added

comment:1 by Johan Råde <johan.rade@…>, 11 years ago

Additional info: I ran the code on Windows XP.

comment:2 by Ralf W. Grosse-Kunstleve, 11 years ago

Resolution: invalid
Status: newclosed

This is not a bug. Construction of boost::python::object from a raw pointer is not supported. Try this (didn't try to compile this, but I tested the idea):

boost::python::object create(char c)
{
    if(c == 'X')
        return boost::python::object(boost::shared_ptr<X>(new X));
    else if(c == 'Y')
        return boost::python::object(boost::shared_ptr<Y>(new Y));
    else if(c == 'Z')
        return boost::python::object(boost::shared_ptr<Z>(new Z));
    else
        throw std::exception("The function argument must be 'X', 'Y' or 'Z'.");
}

with

    class_<X, boost::shared_ptr<X>, noncopyable>("X").def("hello", &X::hello);

etc.

comment:3 by Johan Råde <johan.rade@…>, 11 years ago

Thank you! I have tested it and it works.

Note: See TracTickets for help on using tickets.