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:11【Xiangdi】
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 :
Expression | Type | Result/Semantics |
---|---|---|
x.precall(a) | convertible to bool | returns false and PyErr_Occurred() != 0 upon failure, true otherwise. |
P::result_converter | A 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_type | A 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;
};
}}
Parameter | Requirements | Default |
---|---|---|
ResultConverterGenerator | ResultConverterGenerator Model of | |
Base | CallPolicies 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 :
Expression | Type | Semantics |
---|---|---|
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 .
Expression | Requirements |
---|---|
G::apply::type | A 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
The sidebar is recommended
- Python development alert notification SMS alert
- How to configure Python environment library offline in FME
- Python: fastapi - beginner interface development
- Generate password based on fast token and fast token
- [Django CI system] use of json-20220509
- [Django CI system] if the front-end date is complete, it will be fully updated to the back-end; If the front-end date is incomplete, the date will not be updated to the back-end-20220510
- [Django CI system] echarts dataset standard writing - 20220509
- [Django CI system] obtain the current time, the first day and the last day of the month, etc. - 20220510
- wxPython wx. Correction of font class · Wx Font tutorial
- NCT youth programming proficiency level test python programming level 3 - simulation volume 2 (with answers)
guess what you like
Design of personal simple blog system based on Django (with source code acquisition method)
[Python Script] classify pictures according to their definition
Wu Enda's classic ml class is fully upgraded! Update to Python implementation and add more intuitive visual teaching
Six built-in functions called immortals in Python
Some insights of pandas in machine learning
Introduction to Python [preliminary knowledge] - programming idea
Stay up late to tidy up! Pandas text processing Encyclopedia
Python recursion to find values by dichotomy
Open 3D Python Interface
[true title 02 of Blue Bridge Cup] Python output natural number youth group analysis of true title of Blue Bridge Cup Python national competition
Random recommended
- Introduction to the differences between Python and Java
- Explain Python CONDA in detail
- The pycham downloaded by MAC reports an error as soon as it is opened. The downloaded Python interpreter is also the latest version
- From entry to mastery, python full stack engineers have personally taught Python core technology and practical combat for ten years
- Python is used to detect some problems of word frequency in English text.
- How to choose between excel, database and pandas (Python third-party library)?
- WxPython download has been reporting errors
- Pyside6 UIC and other tools cannot be found in the higher version of pyside6 (QT for Python 6). How to solve it?
- About Python Crawlers
- Successfully imported pandas, unable to use dataframe
- How to extract some keywords in the path with Python
- Python encountered a problem reading the file!
- When Python is packaged into exe, an error is reported when opening assertionerror: C: \ users \ Acer \ appdata \ local \ temp\_ MEI105682\distutils\core. pyc
- Eight practical "no code" features of Python
- Python meets SQL, so a useful Python third-party library appears
- 100 Python algorithm super detailed explanation: a hundred dollars and a hundred chickens
- [fundamentals of Python] Python code and so on
- When Python uses probit regression, the program statement is deleted by mistake, and then it appears_ raise_ linalgerror_ Unrecognized error of singular
- Python testing Nicholas theorem
- Accelerating parallel computing based on python (BL) 136
- Python dynamic programming (knapsack problem and longest common substring)
- Django uses queryset filter save, and an 'queryset' object has no attribute 'Save' error occurs. Solution?
- Analysis of built-in functions in Python learning
- Python office automation - 90 - file automation management - cleaning up duplicate files and batch modifying file names
- Python office automation - 91 - word file Automation - word operation and reading word files
- After python, go also runs smoothly on the browser
- Self taught Python 26 method
- Summary of Python Tkinter component function examples (code + effect picture) (RadioButton | button | entry | menu | text)
- Python implementation of official selection sorting of Luogu question list
- Application of Django template
- Get project root path and other paths in Python project
- Get, rename, and delete file names in Python projects
- How to set the width and height of Python operation table
- Python string preceded by 'f' R 'B' U '
- JSON and other types convert to each other in Python
- Key value of key combination in pynput in Python
- Conversion of Python PDF file to word file
- Interface testing uses Python decorators
- Get the current time in Python
- Python course notes -- Python string, detailed explanation of related functions