current position:Home>Boost(6):Boost. How Python converts C + + parameter and return value types

Boost(6):Boost. How Python converts C + + parameter and return value types

2022-05-15 06:02:11Xiangdi

summary

In the use of Boost.Python transformation C++ Program to Python In the process of interface , We often need to deal with C++ Parameters and return types , But different programming languages , The supported data types will be very different . Although for int/string And other simple data types ,C++ and Python It can be used directly without any processing , But like C++ Citation in 、 class 、 Pointers and STL Wait in Python Data types not available in , Need Boost.Python Additional processing can be done in python Used in program .

such as , Package below c++ function :

struct Y
{
    
    X x; Z* z;
    int z_value() {
     return z->value(); }
};

X& f(Y& y, Z* z)
{
    
    y.z = z;
    return y.x;
}

stay Python You can't call... Directly in the program X Methods , Although the results can be copied to a new Python In the object , Such as :

>>> f(y, z).set(42) # Result disappears
>>> y.x.get()       # No crash, but still bad
3.14

But it goes against Boost.Python I hope to restore... As much as possible C++ The original intention of the interface , And if C++ The function is a little more complex , This method will fail again .

In order to deal with these complex situations ,Boost.Python Three processing models are designed to correspond to different objectives and situations .

Boost.Python The strategy of

Boost.Python The three strategies are as follows :

  • CallPolicies Strategy : Definition Boost.Python transformation C++ Object generated Python Behavior of objects .
  • ResultConverter Strategy : Define how to C++ The return value of is converted to _python.
  • ResultConverterGenerator Strategy : This is a ResultConverter Model generator

A variety of models are defined under each model ( With class In the form of ), The user does not directly call the above policy when using , Instead, use the model under the strategy . Different models specify different functions and objectives , Common models are as follows :

  • with_custodian_and_ward: Ties lifetimes of the arguments
  • with_custodian_and_ward_postcall: Ties lifetimes of the arguments and results
  • return_internal_reference: Ties lifetime of one argument to that of result
  • return_value_policy with T one of:
  • reference_existing_object: naive (dangerous) approach
    • copy_const_reference: Boost.Python v1 approach
    • copy_non_const_reference:
    • manage_new_object: Adopt a pointer and hold the instance

notes : stay Boost.Python There is a small confusion in the description in the official documents , That is, the model and strategy are not clearly separated , Some places use strategy , Some places use models . To make this clear , Define three broad categories as policies , Its concrete implementation is called model .


How to use Boost.Python Model

On the surface of the above f() Function as an example , We're defining it as Python Interface can be :

def("f", f,
    return_internal_reference<1, with_custodian_and_ward<1, 2> >());
  • return_internal_reference<1 : Return the first parameter Y& y Own internal references X&.
  • with_custodian_and_ward<1, 2> : notice Boost.Python ward Indicates the life cycle of the parameter ( That's the second parameter :Z* z) Depending on custodian Indicates the life cycle of the parameter ( The first parameter :Y& y).

In the above example, we defined two policies , If you need to define multiple policies , It can be nested :

policy1<args...,
    policy2<args...,
        policy3<args...> > >


CallPolicies Strategy

CallPolicies The policy specifies Boost.Python take C++ Object conversion to Python After the object , The latter's behavior . In other words, this strategy and its defined model are mainly used to encapsulate C++ class .

Define this in the model Python Four behaviors of objects :

  • precall - Python Before the object is called Python Parameter tuple management
  • result_converter - How to deal with it C++ Return value
  • postcall - Calling Python Object to manage parameter tuples and results
  • extract_return_type - A meta function used to extract a return type from a given type sequence

That is all CallPolicies All models under the policy should implement the functions in the following table :

ExpressionTypeResult/Semantics
x.precall(a)convertible to boolreturns false and PyErr_Occurred() != 0 upon failure, true otherwise.
P::result_converterA model of ResultConverterGenerator.An MPL unary Metafunction Class used produce the “preliminary” result object.
x.postcall(a, r)convertible to PyObject*0 and PyErr_Occurred() != 0 upon failure. Must “conserve references” even in the event of an exception. In other words, if r is not returned, its reference count must be decremented; if another existing object is returned, its reference count must be incremented.
P::extract_return_typeA model of Metafunction.An MPL unary Metafunction used extract the return type from a given signature. By default it is derived from mpl::front.

In order to use multiple... In the same callable object CallPolicies Model ,Boost.Python Of CallPolicies Class template provides a link interface , Allow them to be combined recursively . This interface adopts optional template parameters Base In the form of , The default is default_call_policies.

Usually ,Base Of precall Function in the external template precall Call after function , postcall Function in the external template postcall Call before function , If the external template provides result_converter function , It will replace Base Any... Provided result_converter function .

stay Boost.Python in Contains multiple CallPolicies Strategy :default_call_policies, return_arg.hpp, return_internal_reference and with_custodian_and_ward.

default_call_policies Model

default_call_policies yes CallPolicies A model of , The model is not called before (precall) Or after calling (postcall) act , And there is a process that returns by value result_converter. Encapsulated by default C++ Functions and member functions use this model , If necessary , You can specify other models or derive such models .

Part of the implementation code is as follows :

// boost/python/default_call_policies.hpp

struct default_call_policies
{
    
    // Ownership of this argument tuple will ultimately be adopted by
    // the caller.
    template <class ArgumentPackage>
    static bool precall(ArgumentPackage const&)
    {
    
        return true;
    }

    // Pass the result through
    template <class ArgumentPackage>
    static PyObject* postcall(ArgumentPackage const&, PyObject* result)
    {
    
        return result;
    }

    typedef default_result_converter result_converter;
    typedef PyObject* argument_package;

    template <class Sig> 
    struct extract_return_type : mpl::front<Sig>
    {
    
    };

};

struct default_result_converter
{
    
    template <class R>
    struct apply
    {
    
        typedef typename mpl::if_<
            mpl::or_<detail::is_pointer<R>, detail::is_reference<R> >
          , detail::specify_a_return_value_policy_to_wrap_functions_returning<R>
          , boost::python::to_python_value<
                typename detail::value_arg<R>::type
            >
        >::type type;
    };
};

// Exceptions for c strings an PyObject*s
template <>
struct default_result_converter::apply<char const*>
{
    
    typedef boost::python::to_python_value<char const*const&> type;
};

template <>
struct default_result_converter::apply<PyObject*>
{
    
    typedef boost::python::to_python_value<PyObject*const&> type;
};

You can see ,default_result_converter Under class precall and postcall All functions are empty , That is, do not deal with these two behaviors .default_result_converter Class is ResultConverterGenerator Model of , Can be used for packaging C++ function , Returns a non pointer type by value 、char const* and PyObject*.

This model is also the base class of other models .

Examples of use
stay Boost A default is provided in the source code of CallPolicies The structure of the body , As mentioned above . By default , stay Boost This structure is also used internally , But if the user wants to have other different functions , You can also use the example above , Build your own CallPolicies. It is used in the same way as ordinary structures , It can be wrapped in other structures as an element instance ( This kind of structure is in Boost There are a lot of applications in ) Such as :

template <class Class, class CallPolicies = boost::python::default_call_policies>
struct def_init
{
    
  def_init(Class& cl, CallPolicies call_policies = CallPolicies())
    : cl(cl)
    , call_policies(call_policies)
  {
    }
  
  ...
  
  Class& cl;
  CallPolicies call_policies;
};

It can also be converted into python Interface is specified directly , Such as :

// default.cpp
BOOST_PYTHON_MODULE(defaults_ext)
{
    
    ...
    class_<X>("X",no_init)

        .def(init<optional<int, char, std::string, double> >("doc of init", args("self", "a", "b", "c", "d")))
        .def(init<std::string, bool>(args("self", "s", "b"))[default_call_policies()]) // what's a good policy here?
        ...
        ;
}


return_arg and return_self Model

return_arg And its derivatives return_self The example of is based on default_call_policies Model of , The encapsulation function using this model will return the specified parameters (return_arg Is the specified parameter , and return_self Usually *this).

// boost/python/return_arg.hpp
// class return_arg
namespace boost {
     namespace python
{
    
   template <size_t arg_pos=1, class Base = default_call_policies>
   struct return_arg : Base
   {
    
      static PyObject* postcall(PyObject*, PyObject* result);
      struct result_converter{
     template <class T> struct apply; };
      template <class Sig> struct extract_return_type : mpl::at_c<Sig, arg_pos>{
    };

   };
}}

// class return_self
namespace boost {
     namespace python
{
    
   template <class Base = default_call_policies>
   struct return_self
     : return_arg<1,Base>
   {
    };
}}

among arg_pos=1 Indicates the position of the parameter to be returned .

Examples of use
C++ code:

#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/return_arg.hpp>

struct Widget
{
    
   Widget() :sensitive_(true){
    }
   bool get_sensitive() const {
     return sensitive_; }
   void set_sensitive(bool s) {
     this->sensitive_ = s; }
 private:
   bool sensitive_;
};

struct Label : Widget
{
    
   Label() {
    }

   std::string  get_label() const {
     return label_; }
   void set_label(const std::string &l){
     label_ = l; }

 private:
   std::string label_;
};

using namespace boost::python;
BOOST_PYTHON_MODULE(return_self_ext)
{
    
   class_<widget>("Widget")
      .def("sensitive", &Widget::get_sensitive)
      .def("sensitive", &Widget::set_sensitive, return_self<>())
      ;

   class_<Label, bases<Widget> >("Label")
      .def("label", &Label::get_label)
      .def("label", &Label::set_label, return_self<>())
      ;
}

Python code:

>>> from return_self_ext import *
>>> l1 = Label().label("foo").sensitive(false)
>>> l2 = Label().sensitive(false).label("foo")

Use return_self After the model , although C++ in ,set_label() Function does not return a value , however Python in label(“foo”) Returned a callable Python object (Label Object itself ).

return_internal_reference Model

This class can be used without copying , Directly return the pointer or reference of the encapsulated function . Point around C++ The pointer of the result object constructs a Python object , If Python The result is effective , Then apply some life cycle management to keep “self” The activity of objects .NULL The pointer returns None.

Part of the implementation code is as follows :

// boost/python/return_internal_reference.hpp
namespace boost {
     namespace python
{
    
   template <std::size_t owner_arg = 1, class Base = default_call_policies>
   struct return_internal_reference : Base
   {
    
      static PyObject* postcall(PyObject*, PyObject* result);
      typedef reference_existing_object result_converter;
   };
}}

owner_arg=1 Indicates the parameter index of the reference or pointer object to be returned . If used to encapsulate member functions , The parameter 1 It's the target (*this). It should be noted that , If target Python Object types do not support weak references , Will be raised when calling the encapsulated function Python TypeError abnormal .

Base = default_call_policies Indicates that its parent class is default_call_policies.

Examples of use
C++ code:

#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/return_internal_reference.hpp>

class Bar
{
    
 public:
   Bar(int x) : x(x) {
    }
   int get_x() const {
     return x; }
   void set_x(int x) {
     this->x = x; }
 private:
   int x;
};

class Foo
{
    
 public:
   Foo(int x) : b(x) {
    }

   // Returns an internal reference
   Bar const& get_bar() const {
     return b; }

 private:
   Bar b;
};

using namespace boost::python;
BOOST_PYTHON_MODULE(internal_refs)
{
    
   class_<Bar>("Bar", init<int>())
      .def("get_x", &Bar::get_x)
      .def("set_x", &Bar::set_x)
      ;

   class_<Foo>("Foo", init<int>())
      .def("get_bar", &Foo::get_bar
          , return_internal_reference<>())
      ;
}

Python code:

>>> from internal_refs import *
>>> f = Foo(3)
>>> b1 = f.get_bar()
>>> b2 = f.get_bar()
>>> b1.get_x()
3
>>> b2.get_x()
3
>>> b1.set_x(42)
>>> b2.get_x()
42

C++ in Foo() The return value of is a class Bar, stay Python In the program , Foo() The returned object is based on Bar Class pointer construction Python

return_value_policy Model

return_value_policy Instantiation is CallPolicies A simple model of , from ResultConverterGenerator And optional Base CallPolicies form . To produce Python Return value policy .

Part of the definition is as follows :

// boost/python/return_value_policy.hpp
namespace boost {
     namespace python
{
    
  template <class ResultConverterGenerator, class Base = default_call_policies>
  struct return_value_policy : Base
  {
    
      typedef ResultConverterGenerator result_converter;
  };
}}
ParameterRequirementsDefault
ResultConverterGeneratorResultConverterGenerator Model of
BaseCallPolicies Model default_call_policies

Examples of use
Use return_value_policy The model also needs to specify the additional ResultConverterGenerator Model . Specific view ResultConverterGenerator Model .
C++ code:

#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/copy_const_reference.hpp>
#include <boost/python/return_value_policy.hpp>

// classes to wrap
struct Bar {
     int x; }

struct Foo {
    
   Foo(int x) : {
     b.x = x; }
   Bar const& get_bar() const {
     return b; }
 private:
   Bar b;
};

// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
    
   class_<Bar>("Bar");

   class_<Foo>("Foo", init<int>())
      .def("get_bar", &Foo::get_bar
          , return_value_policy<copy_const_reference>())
      ;
}

there copy_const_reference Represents the encapsulation function get_bar() Return to one const Embellished references .

Python code:

>>> from my_module import *
>>> f = Foo(3)         # create a Foo object
>>> b = f.get_bar()    # make a copy of the internal Bar object


with_custodian_and_ward and with_custodian_and_ward_postcall Model

These two classes are in two of the functions Python A tool for establishing lifecycle dependencies between parameters or result objects . as long as Python Object supports weak references , The parameters or results specified by these two classes will remain valid until the object is destroyed .

To avoid inadvertently creating null pointers , By default, when calling the underlying C++ Object before life cycle binding . But the result object is not available before the call , So it provides with_custodian_and_ward_postcall To bind the life cycle after the call .

Note: These two classes need the target Python Object supports weak references , Otherwise it will trigger Python TypeError abnormal .

Part of the implementation code is as follows :

// boost/python/with_custodian_and_ward.hpp

namespace boost {
     namespace python
{
    
   template <std::size_t custodian, std::size_t ward, class Base = default_call_policies>
   
   struct with_custodian_and_ward : Base
   {
    
      static bool precall(PyObject* args);
   };
   
   struct with_custodian_and_ward_postcall : Base
   {
    
      static PyObject* postcall(PyObject* args, PyObject* result);
   };
}}
  • custodian : Parameter index indicating the beginning of the binding life cycle ;1 Represents the first parameter ; If used to encapsulate member functions , The parameter 1 Represents the target object (*this). about with_custodian_and_ward_postcall, 0 Represents the result object ;
  • ward : Indicates the maximum parameter index of the binding declaration cycle .
  • Base : CallPolicies Model , The default is default_call_policies

Examples of use
with_custodian_and_ward
for example , Container operation append Usually use with_custodian_and_ward<1,2>, This means keeping the parameters active while the container itself is active .

// c++
void reg(Creator* c) {
     mC = c; }

// python wrapper
.def("reg", &Factory::reg, with_custodian_and_ward<1,2>())

with_custodian_and_ward_postcall
// c++
request_with_value
communicator_irecv_content(const communicator& comm, int source, int tag,
                           content& c)
{
    
  request_with_value req(comm.irecv(source, tag, c.base()));
  req.m_external_value = &c.object;
  return req;
}

// python wrapper
.def("irecv", communicator_irecv_content,
     (arg("source") = any_source, arg("tag") = any_tag, arg("buffer")),
     with_custodian_and_ward_postcall<0, 4>()
     );


ResultConverter Strategy

ResultConverter The policy specifies how C++ The return value of is converted to _python Return value .
From the document , all ResultConverter All models in the following table should realize the functions in the following table :

ExpressionTypeSemantics
C c Construction example c
c.convertible()convertible to bool No if R Value to Python object , Then for false.
c (r)convertible to PyObject* Point to correspond to r Of Python Object pointer . If r Cannot convert to _python, Start now PyErr_Occurred.
c.get_pytype()PyTypeObject const * Point to... Corresponding to the conversion result Python Type Object pointer . If used to generate documents , The value is 0.

notes : The above table comes from Boost.Python Official documents of , But I didn't find the above in the source code convertible() Implementation of function .


to_python_indirect Model

<boost/python/to_python_indirect.hpp> Provides a way to construct new Python object , These pointers or smart objects are saved by wrapping them C++ Class instance .

Template class to_python_indirect Use the ownership policy provided by the second parameter to convert the object of the first parameter type to python object .
Part of the implementation code is as follows :

namespace boost {
     namespace python {
    

template <class T, class MakeHolder>
struct to_python_indirect
{
    
    template <class U>
    inline PyObject* operator()(U const& ref) const;
    inline PyTypeObject const* get_pytype()const;
    
 private:
    template <class U>
    inline PyObject* execute(U* ptr, detail::true_) const;
    
    template <class U>
    inline PyObject* execute(U const& x, detail::false_) const;
};
}}
  • T Indicates to convert to Python Type of C++ class .
  • operator() The function creates an appropriate type of Boost.Python Extension class instance , Use MakeHolder from x Create a instance_holder, take instance_holder Install in a new extension class instance , And returns a pointer to it .

notes : This part is copied from the source code , There is a discrepancy with the document .

Examples of use
This example reproduces reference_existing_object The function of , But there are no compile time error checks .

struct make_reference_holder
{
    
   typedef boost::python::objects::instance_holder* result_type;
   template <class T>
   static result_type execute(T* p)
   {
    
      return new boost::python::objects::pointer_holder<T*, T>(p);
   }
};

struct reference_existing_object
{
    
   // metafunction returning the ResultConverter
   template <class T>
   struct apply
   {
    
      typedef boost::python::to_python_indirect<T,make_reference_holder> type;
   };
};


to_python_value Model

to_python_value yes ResultConverter A model of , It will C++ Copy parameters to a new Python In the object .

template <class T>
struct to_python_value
    : mpl::if_< detail::value_is_shared_ptr<T> , detail::shared_ptr_to_python_value<T> , typename mpl::if_< mpl::or_< converter::is_object_manager<T> , converter::is_reference_to_object_manager<T> > , detail::object_manager_to_python_value<T> , detail::registry_to_python_value<T> >::type >::type
{
    
};

similarly , The code here is also very different from the document .

notes : It is used more as a template class for other classes , In actual development Boost.Python I haven't seen any specific application using this strategy when converting the program .


ResultConverterGenerator Strategy

ResultConverterGenerator It's a MPL Unary function class , For given C++ The return type of the function T, This class returns this type T Of ResultConverter. Boost.Python Medium ResultConverters Usually check the converter registry of the library to find the appropriate Converter , But a converter that does not use the registry is also possible .

In the table below ,G Express ResultConverterGenerator type ,R Indicates possible C++ Function return type .

ExpressionRequirements
G::apply::typeA ResultConverter type for R.

As said before, , ResultConverterGenerator The next model needs to be consistent with CallPolicies Of return_value_policy Use a combination of . namely return_value_policy Medium T,
To produce Python Return value policy .

The models included in this strategy are :

  • reference_existing_object : Returns an existing instance of Python object
  • copy_non_const_reference : Return a useless const Decorated object ,C++ The object will be copied to Python In the object
  • copy_const_reference : Return a message with const Decorated object ,C++ The object will be copied to Python In the object
  • manage_new_object : Returns a newly allocated object from the heap , Need to be in Python Free the memory space of the object in the program
  • return_by_value : The return value of the encapsulated function is a reference to a simple data type , Such as int, string etc. , These values will be copied to Python in .
  • return_opaqe_pointer : Used to encapsulate a pointer whose return value is an undefined type C++ function , This value is copied to the new Python In the object

reference_existing_object Model

This model is used to modify that the return value is C++ Function of object reference or pointer , Converted Python The return value of the function points to the C++ Object pointer . When calling the wrapper function , The value referenced by its return value... Will not be copied . It's about creating a new Python object , The object contains a unowned U* The pointer , The pointer points to the object to which the return value of the encapsulation function points .

The strategy is return_internal_reference Applied . NULL The pointer also returns None.

Examples of use

#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/reference_existing_object.hpp>
#include <boost/python/return_value_policy.hpp>
#include <utility>

// classes to wrap
struct Singleton
{
    
   Singleton() : x(0) {
    }

   int exchange(int n)  // set x and return the old value
   {
    
        std::swap(n, x);
        return n;
   }

   int x;
};

Singleton& get_it()
{
    
   static Singleton just_one;
   return just_one;
}

// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(singleton)
{
    
    def("get_it", get_it,
        return_value_policy<reference_existing_object>());

    class_<Singleton>("Singleton")
       .def("exchange", &Singleton::exchange)
       ;
}

Python in get_it() Function will return Singleton Pointer object of the instance .

>>> import singleton
>>> s1 = singleton.get_it()
>>> s2 = singleton.get_it()
>>> id(s1) == id(s2)  # s1 and s2 are not the same object
0
>>> s1.exchange(42)   # but they reference the same C++ Singleton
0
>>> s2.exchange(99)
42


copy_non_const_reference Model

Used to encapsulate the return of non const Refer to the C++ function , To copy the referenced value to the new Python In the object .

Examples of use

#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/copy_non_const_reference.hpp>
#include <boost/python/return_value_policy.hpp>

// classes to wrap
struct Bar {
     int x; }

struct Foo {
    
   Foo(int x) : {
     b.x = x; }
   Bar& get_bar() {
     return b; }
 private:
   Bar b;
};

// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
    
    class_<Bar>("Bar");

     class_<Foo>("Foo", init<int>())
        .def("get_bar", &Foo::get_bar
            , return_value_policy<copy_non_const_reference>())
       ;
}
>>> from my_module import *
>>> f = Foo(3)         # create a Foo object
>>> b = f.get_bar()    # make a copy of the internal Bar object


copy_const_reference Model

Used to encapsulate and return a reference to a constant type C++ function , To copy the referenced value to the new Python In the object .

Examples of use

#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/copy_const_reference.hpp>
#include <boost/python/return_value_policy.hpp>

// classes to wrap
struct Bar {
     int x; }

struct Foo {
    
   Foo(int x) : {
     b.x = x; }
   Bar const& get_bar() const {
     return b; }
 private:
   Bar b;
};

// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
    
    class_<Bar>("Bar");

     class_<Foo>("Foo", init<int>())
        .def("get_bar", &Foo::get_bar
            , return_value_policy<copy_const_reference>())
       ;
}
>>> from my_module import *
>>> f = Foo(3)         # create a Foo object
>>> b = f.get_bar()    # make a copy of the internal Bar object


manage_new_object Model

This model is used to return the newly allocated object that encapsulates the function , Such as new Object of statement . It should be noted that , image c++ Same operation in , The user needs to manually delete the object from the heap .

Examples of use

#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/manage_new_object.hpp>
#include <boost/python/return_value_policy.hpp>


struct Foo {
    
   Foo(int x) : x(x){
    }
   int get_x() {
     return x; }
   int x;
};

Foo* make_foo(int x) {
     return new Foo(x); }

// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
    
    def("make_foo", make_foo, return_value_policy<manage_new_object>())
    class_<Foo>("Foo")
        .def("get_x", &Foo::get_x)
        ;
}
>>> from my_module import *
>>> f = make_foo(3)     # create a Foo object
>>> f.get_x()
3


return_by_value Model

This model is used to encapsulate that the return value of a function is any type of reference or value . The return value is copied to a new Python In the object . The reference or value here refers to the common data type , Such as string, int etc. c++ and python Common basic data types .

Examples of use

#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/return_by_value.hpp>
#include <boost/python/return_value_policy.hpp>

// classes to wrap
struct Bar {
     };

Bar global_bar;

// functions to wrap:
Bar b1();
Bar& b2();
Bar const& b3();

// Wrapper code
using namespace boost::python;
template <class R>
void def_void_function(char const* name, R (*f)())
{
    
   def(name, f, return_value_policy<return_by_value>());
}

BOOST_PYTHON_MODULE(my_module)
{
    
    class_<Bar>("Bar");
    def_void_function("b1", b1);
    def_void_function("b2", b2);
    def_void_function("b3", b3);
}
>>> from my_module import *
>>> b = b1() # each of these calls
>>> b = b2() # creates a brand
>>> b = b3() # new Bar object


return_opaqe_pointer Model

This model is used to encapsulate a pointer whose return value is an undefined type C++ function , This value is copied to the new Python In the object .

In addition to designating return_opaque_pointer Out of strategy , You must also use BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID Macro to define the type pointed to by the returned pointer type_id Specialization of function .

Examples of use

# include <boost/python/return_opaque_pointer.hpp>
# include <boost/python/def.hpp>
# include <boost/python/module.hpp>
# include <boost/python/return_value_policy.hpp>

typedef struct opaque_ *opaque;

opaque the_op   = ((opaque) 0x47110815);

opaque get () {
     return the_op; }
void use (opaque op) {
    
    if (op != the_op)
	throw std::runtime_error (std::string ("failed"));
}

void failuse (opaque op) {
    
    if (op == the_op)
	throw std::runtime_error (std::string ("success"));
}

BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque_)

namespace bpl = boost::python;

BOOST_PYTHON_MODULE(opaque_ext)
{
    
    bpl::def (
        "get", &::get, bpl::return_value_policy<bpl::return_opaque_pointer>());
    bpl::def ("use", &::use);
    bpl::def ("failuse", &::failuse);
}
""" >>> from opaque_ext import * >>> # >>> # Check for correct conversion >>> use(get()) >>> failuse(get()) Traceback (most recent call last): ... RuntimeError: success >>> # >>> # Check that there is no conversion from integers ... >>> use(0) Traceback (most recent call last): ... TypeError: bad argument type for built-in operation >>> # >>> # ... and from strings to opaque objects >>> use("") Traceback (most recent call last): ... TypeError: bad argument type for built-in operation """
def run(args = None):
    import sys
    import doctest

    if args is not None:
        sys.argv = args
    return doctest.testmod(sys.modules.get(__name__))

if __name__ == '__main__':
    print "running..."
    import sys
    sys.exit(run()[0])


Reference material

boost.python/CallPolicy
Boost.Python - Chapter 1. Concepts
Boost Call Policies
Models of CallPolicies
ResultConverter
Models of ResultConverterGenerator
Models of ResultConverter

copyright notice
author[Xiangdi],Please bring the original link to reprint, thank you.
https://en.pythonmana.com/2022/131/202205110608081631.html

Random recommended