Differences between revisions 7 and 8
Revision 7 as of 2002-10-10 16:02:53
Size: 3495
Editor: MikeRovner
Comment:
Revision 8 as of 2002-11-15 19:41:36
Size: 3542
Editor: MikeRovner
Comment: v2
Deletions are marked like this. Additions are marked like this.
Line 19: Line 19:
BOOST_PYTHON_MODULE_INIT(test_pointer_adoption_ext) BOOST_PYTHON_MODULE(test_pointer_adoption_ext)
Line 37: Line 37:
 * `no_init` means "do not try to define a Python __init__ function"  * `no_init` means "do not try to create an instance of that Python object - __init__ function that throws an exception"

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(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 create an instance of that Python object - init function that throws an exception"

  • 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.


4. How to I expose static class data members ?

object x_class
    = class_<X>("X")
         .def( ... )
         ...
         ;

x_class.attr("fu") = X::fu;
x_class.attr("bar") = X::bar;
...


4. Why operators.hpp imports certain functions (such as 'str') into the global namespace, instead of the namespace boost::python. That looks like an error...

It's only on broken compilers which don't support KoenigLookup, and it's intentional. The negative impact should be limited due to the fact that these functions only operate on objects of type boost::python::self_ns::self_t. Do you anticipate a real problem with this?

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.