Differences between revisions 4 and 5
Revision 4 as of 2002-09-26 20:35:06
Size: 1426
Editor: MikeRovner
Comment:
Revision 5 as of 2002-10-02 17:36:04
Size: 2827
Editor: MikeRovner
Comment: creating Python objects from C++
Deletions are marked like this. Additions are marked like this.
Line 40: Line 40:
3. ''Is it is possible to convert pointers to existing classes to PyObjects* and then be
able to pass an existing instance of an object directly to and from python?''

It is.

Example:
In C++ I create a CWheel and I set its member m_diameter to 1233. In
python I have a function that receives a CWheel and displays the
diameter (Lets suppose that Python knows the CWheel from Boost.Python
{{{
def printCWheelDiam(awheel):
    print awheel.m_diameter
}}}
The safest thing to do is to create the CWheel by invoking its class
wrapper:
{{{
    // Declare the CWheel extension class
    object wheel_class =
        class_<CWheel>("CWheel")
            .def_readonly("m_diameter", &CWheel::m_diameter)
            .def("some_member_function", &CWheel::some_member_function)
            ...
            ;

    object wheel_obj = wheel_class(); // construct one
}}}
Now you can pass wheel_obj back to python, and all reference counts are
nicely managed. You don't need to "map" anything between C++ and Python;
the library takes care of that for you.

If you really want to pass pointers around, it's certainly possible to tell
the library to build a Python object around the pointer, but then you need
to make sure the lifetime of the C++ object being referenced by the pointer
extends past the lifetime of all Python references to the object or your
program will crash.

From comp.python.c++ newsgroup:


1. The constructors of some classes I am trying to wrap are private because instances must be created by using a factory. Is it possible to wrap such classes using bpl v2?

Sure. Of course you can only create the instances using the factory...

If you look at libs/python/test/test_pointer_adoption.cpp you'll see the factory function "create" is being used to generate new instances of class A. It uses return_value_policy<manage_new_object> to instruct Python to adopt the A* to hold the instance.

A* create(std::string const& s)
{
    return new A(s);
}

BOOST_PYTHON_MODULE_INIT(test_pointer_adoption_ext)
{
        def("num_a_instances", num_a_instances);

        // Specify the manage_new_object return policy to take
        // ownership of create's result
        def("create", create, return_value_policy<manage_new_object>());
        
        class_<A>()
            .def("content", &A::content)
            .def("get_inner", &A::get_inner, return_internal_reference<>())
        ;
}


2. What is the relation between this no_init and boost::noncopyable?

The only relationship is that they both deal with constructors.

  • no_init means "do not try to define a Python init function"

  • noncopyable means "do not try to register a converter which can convert C++ T return values to python".


3. Is it is possible to convert pointers to existing classes to PyObjects* and then be able to pass an existing instance of an object directly to and from python?

It is.

Example: In C++ I create a CWheel and I set its member m_diameter to 1233. In python I have a function that receives a CWheel and displays the diameter (Lets suppose that Python knows the CWheel from Boost.Python

def printCWheelDiam(awheel):
    print awheel.m_diameter

The safest thing to do is to create the CWheel by invoking its class wrapper:

    // Declare the CWheel extension class
    object wheel_class =
        class_<CWheel>("CWheel")
            .def_readonly("m_diameter", &CWheel::m_diameter)
            .def("some_member_function", &CWheel::some_member_function)
            ...
            ;

    object wheel_obj = wheel_class(); // construct one

Now you can pass wheel_obj back to python, and all reference counts are nicely managed. You don't need to "map" anything between C++ and Python; the library takes care of that for you.

If you really want to pass pointers around, it's certainly possible to tell the library to build a Python object around the pointer, but then you need to make sure the lifetime of the C++ object being referenced by the pointer extends past the lifetime of all Python references to the object or your program will crash.

boost.python/FAQ (last edited 2010-10-26 02:02:04 by c-67-188-38-165)

Unable to edit the page? See the FrontPage for instructions.