current position:Home>Boost(8):Boost. Python implements Python objects and various types of built-in operations and methods

Boost(8):Boost. Python implements Python objects and various types of built-in operations and methods

2022-05-15 06:02:35Xiangdi

explain

Python There are many very useful data types , Such as Numbers,String,List,Tuple,Dictionary and Set. In the previous example, we often use Numbers and String( Their content ) Can be directly in C++ The code uses , Because these two are also C++ Data type of ( Although the implementation is different , But it does not prevent the two from being common ). But other types of data structures are C++ Not in China , So when Python These types are required and are compatible with C++ When code has interaction , How to deal with it ?

stay Boost.Python and C++ From the point of view of , these Pythonic Variables are just instances of class objects .Python Every variable or method of is a Python object , All these attributes , And Python Give these objects built-in methods one way or another , So that we can use them easily .Boost.Python The library provides a file named object Class , It can encapsulate an effective Python Object and provides a connection with Python Similar interface . In other words , every last Python Objects can be used as Boost.Python One of the object Class instance , meanwhile Boost.Python This example is provided close to Python Syntax operation support , These supports are mainly implemented in the form of operator overloading . such as :

PythonC++ explain
y = x.fooy = x.attr(“foo”); obtain x The attribute value , Usually member variables
x.foo = 1x.attr(“foo”) = 1; Set up x Properties of
y = x[z]y = x[z]; list / Dictionary operation
x[z] = 1x[z] = 1; list / Dictionary operation
y = x[3:-1]y = x.slice(3,-1); Slicing operation
y = x[3:]y = x.slice(3,_);
y = x[:-2]y = x.slice(_,-2);
z = x(1, y)z = x(1, y); Call function
z = x.f(1, y)z = x.attr(“f”)(1, y); Call member functions
not x!x Logic is not
x and yx && y Logic and

Boost.Python One of our goals is to provide C++ and Python Two way mapping between , Keep at the same time Python The feeling of . Boost.Python C++ The object is as close as possible to Python. In the operation example in the above table , Although not completely consistent , however Boost.Python As far as possible, it provides information that conforms to C++ Grammar and Python Consistent functions .

Above Python data type , except Set Outside ,Boost.Python Treat it as an instance of a class . How to understand that , For example, a Python Variable a = [1,2,3,4] It's a List type , So in Boost.Python in a It's a class list example .

Object Class is a base class , For all Python General operation methods of objects , about Python Common data types ,Boost.Python Provides the basis for object Of and Python The derived class corresponding to the type :

  • list
  • dict
  • tuple
  • str
  • long_
  • enum

notes : It doesn't include Set type .

The relationship between these derived classes and base classes is shown in the figure below :
 Insert picture description here
in the light of Python Encapsulation of objects ,Boost.Python Two packaging concepts are proposed : ObjectWrapper and TypeWrapper, The former is used to describe management Python The object of , The latter is specific to Python Object to optimize and improve .

ObjectWrapper

ObjectWrapper Two concepts are defined , Used to describe management Python Ground oriented class , And designed to support the use of similar Python The grammar of .

ObjectWrapper The conceptual model will object As a public base class and used to provide special constructors or other functions through member functions . Unless the return type R Itself is a TypeWrapper, Otherwise, it is a member function call in the form of .
For example, statements

x.some_function(a1, a2,...an)

Equivalent to :

extract<R>(x.attr("some_function")(object(a1), object(a2),...object(an)))()


TypeWrapper

TypeWrapper It's right ObjectWrapper Improvement , It is related to a specific Python type X Related to . For a given TypeWrapper T, A valid constructor expression is :

T(a1, a2,...an)

Building a new T object , Management call X Result , The parameter corresponds to :

object(a1), object(a2),...object(an)

When used as a package C++ Arguments to functions or used as extract<> Template parameters for , Only relevance Python An instance of type is considered a match .

Warning

When the return type is TypeWrapper when , The result of a special member function call is that the returned object may be related to a specific Python Object type mismatch , Usually this is not a serious problem ; The worst result is that errors are detected at runtime a little later than in other cases . An example of how this happens , Please note that dict Member functions items Returns an object of type list . Now suppose the user is Python This is defined in dict Subclass :

>>> class mydict(dict):
...     def items(self):
...         return tuple(dict.items(self)) # return a tuple

because mydict Examples are dict Example , Therefore, when used as packaging C++ Function arguments ,boost::python::dict Acceptable Python type mydict The object of . Call... On this object items() Can lead to boost::python::list Example , It actually contains a Python Tuples . Then try using the list method on this object ( For example, append or any other mutation operation ) Will trigger and attempt from Python The same exception occurred while performing this operation .

Object Base class

Object Classes are generic Python Object's encapsulation class and others TypeWrapper Class base class .object There is a templated constructor , Can be used with call<> The underlying mechanism with the same parameters will be any C++ Object to Python. If an object instance is created without any constructor parameters , Then the value of this instance is None.

object Class encapsulation PyObject*. Handle PyObjects All the complexity of , For example, manage reference counts , Are handled by object classes .Boost.Python C++ Objects can actually be from any C++ Object is explicitly constructed .

Let's start with a simple example , This Python code snippet :

def f(x, y):
     if (y == 'foo'):
         x[3:7] = 'bar'
     else:
         x.items += y(3, x)
     return x

def getfunc():
   return f;

You can use Boost.Python Tools in C++ Rewriting in :

object f(object x, object y) {
    
     if (y == "foo")
         x.slice(3,7) = "bar";
     else
         x.attr("items") += y(3, x);
     return x;
}
object getfunc() {
    
    return object(f);
}

Except because we use C++ The difference between the appearance and the writing of the code ,Python Coders should immediately understand the look and feel familiar .

Object Class provides functions such as slicing , Application of attributes, strategies, operators and other functions , For details, see :boost/python/object.hpp

Object Derived class

Object Derived classes are also mentioned earlier TypeWrapper Your behavior is similar to real Python type . for example :

str(1) ==> "1"

Where appropriate , A specific derived object has a corresponding Python Method of type . for example , dict There is one keys() Method :

d.keys()

make_tuple Used to declare tuples . Example :

make_tuple(123, 'D', "Hello, World", 0.0);

stay C++ in , When Boost.Python Object as an argument to a function , Subtype matching is required . for example , When the function declared below f When packed , It will only accept Python Of str Instances of types and subtypes .

void f(str name)
{
    
    object n2 = name.attr("upper")();   // NAME = name.upper()
    str NAME = name.upper();            // better
    object msg = "%s is bigger than %s" % make_tuple(NAME,name);
}

In more detail :

str NAME = name.upper();

Explain that we provide str The version of the type method is used as C++ Member functions .

object msg = "%s is bigger than %s" % make_tuple(NAME,name);

It means that we can Python Written in “format” % x,y,z The equivalent of C++, It's very useful , Because in the standard C++ There is no easy way to do this .

But here's the thing : Most of the time ,Python and C++ The objects between are copied , If you modify one object, it will not affect the value of another object .

# Python:
>>> d = dict(x.__dict__)     # copies x.__dict__
>>> d['whatever'] = 3        # modifies the copy

// C++ 
dict d(x.attr("__dict__"));  // copies x.__dict__
d['whatever'] = 3;           // modifies the copy


class_ as objects

because Boost.Python Dynamic properties of objects , whatever class_ It could also be one of these types ! We can use it to create wrapper instances . Example :

object vec345 = (
    class_<Vec2>("Vec2", init<double, double>())
        .def_readonly("length", &Point::length)
        .def_readonly("angle", &Point::angle)
    )(3.0, 4.0);

assert(vec345.attr("length") == 5.0);


Creating boost::python::object from PyObject*

When we wish boost::python::object Management points to PyObject* pyobj The pointer of , Sure :

boost::python::object o(boost::python::handle<>(pyobj));

under these circumstances ,o Object management pyobj, It does not increase the reference count at construction time .

otherwise , Refer to boost::python::borrowed

boost::python::object o(boost::python::handle<>(boost::python::borrowed(pyobj)));

under these circumstances , call Py_INCREF, So when the object o When out of range ,pyobj Will not be destroyed .

list class

expose Python Built in list type method . The semantics of constructors and member functions defined below can be read TypeWrapper Concept definition to fully understand . because list It's from object Publicly derived , therefore public object The interface is also applicable to list example .

This class is defined in <boost/python/list.hpp> Header file , Part of the code as follows :

namespace boost {
     namespace python
{
    
  class list : public object
  {
    
   public:
      //  Constructors , Generate a  list  Class instance 
      list(); // new list
      template <class T>
      explicit list(T const& sequence);

      template <class T>
      void append(T const& x);    //  Add a new object at the end of the list 

      template <class T>
      long count(T const& value) const;   //  Add a new object at the end of the list 

      template <class T>
      void extend(T const& x);            //  Appends multiple values from another sequence at once at the end of the list 

      template <class T>
      long index(T const& x) const;     //  Find the index position of the first match of a value in the list 

      template <class T>
      void insert(object const& index, T const& x); // insert object before index

      object pop(); // remove and return item at index (default last)
      object pop(long index);
      object pop(object const& index);

      template <class T>
      void remove(T const& value);       //  Remove from list  value  The first match of 

      void reverse(); // reverse *IN PLACE*

      void sort(); // sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1
      template <class T>
      void sort(T const& value);
  };
}}

Python list Most of the methods supported are Boost.Python list class It is implemented in , And in order to be as close as possible to python Our habits are consistent , The method of function call and parameters are also similar .

Example
Here's a simple reverse() Function as an example , Introduce Boost.Python Of list The use of the class
C++:

#include <iostream>

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

#include <boost/python/list.hpp>

namespace bp = boost::python;

bp::list list_reverse (bp::list &l1)
{
    
    std::cout << "Input list length: " << len(l1) << std::endl;

    l1.reverse();

    return l1;
}

BOOST_PYTHON_MODULE(objects)
{
    
    using namespace boost::python;

    def("list_reverse", list_reverse, args("l1"), return_value_policy<return_by_value>())
    ;
}

Python:

$ python
>>> import objects
>>> a = [1, 3, 6, 2, 9, 0]
>>> objects.list_reverse(a)
Input list length: 6
[0, 9, 2, 6, 3, 1]

ok , This example is boring , The main purpose is to explain when python An interface is passed in list When parameters are ,C++ Can pass Boost.Python Realize the processing of this parameter .

dict class

dict Class is targeted at python Dictionary data type encapsulates object Derived classes , Provides python dict Similar methods and operations . Defined in the file <boost/python/dict.hpp> in .

namespace boost {
     namespace python
{
    
   class dict : public object
   {
    
      dict();    //  Constructors 
      template< class T >
      dict(T const & data);

      // modifiers
      void clear();     //  Delete all elements in the dictionary 
      dict copy();      //  Returns a shallow copy of a dictionary 

      template <class T1, class T2>
      tuple popitem();  //  Returns and deletes the last pair of keys and values in the dictionary .

      //  and get() similar ,  But if the key  k  Does not exist in the dictionary , The key will be added and the value will be set to  d  perhaps  default
      template <class T>
      object setdefault(T const &k);    
      template <class T1, class T2>
      object setdefault(T1 const & k, T2 const & d);

      //  Put the dictionary  E  Key / Value pair update to dict in 
      void update(object_cref E);
      template< class T >
      void update(T const & E);

      //  Returns all values of the dictionary 
      list values() const;

      //  Returns the specified key k Value , If the key is not in the dictionary, return  d  Or default  NULL
      object get(object_cref k) const;
      template<class T>
      object get(T const & k) const;
      object get(object_cref k, object_cref d) const;
      object get(T1 const & k, T2 const & d) const;

      //  If the key is in the dictionary dict Back in true, Otherwise return to false
      bool has_key(object_cref k) const;
      template< class T >
      bool has_key(T const & k) const;

      list items() const;         //  Returns the tuple object of the dictionary as a list 
      object iteritems() const;   //  Returns a dictionary tuple as an iterator 
      object iterkeys() const;    //  Returns the dictionary keyword as an iterator 
      object itervalues() const;  //  Returns the dictionary value as an iterator 
      list keys() const;          //  Return the keyword list of the dictionary 
  };
}}

Example
C++:

bp::dict swap_object_dict(bp::object target, bp::dict d)
{
    
    bp::dict result = bp::extract<bp::dict>(target.attr("__dict__"));
    target.attr("__dict__") = d;
    
    return result;
}

This function will input the dictionary in the parameter d Content and target Of __dict__ Property swap , And will target The original __dict__ Property as a new dictionary output .

Python:

import objects

class O1:
    ''' class O1 '''
    Name = 'Test'
    Age = 0

    def __init__(self):
        self.Name = 'Test'
        self.Age = 0

a = O1()
print(a.__dict__)

d1 = {
    "Name":"Xiangdi", "Age":10}
print(d1)

d2 = objects.swap_object_dict(a, d1)
print(a.__dict__)
print(d2)

Running results :

$ python objects.py
{
    'Na': 'Test', 'Ag': 0}
{
    'Name': 'Xiangdi', 'Age': 10}
{
    'Name': 'Xiangdi', 'Age': 10}
{
    'Na': 'Test', 'Ag': 0}


tuple class

This class encapsulates parts similar to Python tuple Function of data type . But compared with other derived classes , class tuple There are relatively few functions , There is only one constructor . It is characterized by providing a variety of structures tuple Overloaded functions for make_tuple. Its definition is <boost/python/tuple.hpp> in .

namespace boost {
     namespace python
{
    
   class tuple : public object
   {
    
      // tuple() -> an empty tuple
      tuple();

      // tuple(sequence) -> tuple initialized from sequence's items
      template <class T>
      explicit tuple(T const& sequence)
  };
}}

namespace boost {
     namespace python
{
    
  tuple make_tuple();

  template <class A0>
  tuple make_tuple(A0 const& a0);

  template <class A0, class A1>
  tuple make_tuple(A0 const& a0, A1 const& a1);
  ...
  template <class A0, class A1,...class An>
  tuple make_tuple(A0 const& a0, A1 const& a1,...An const& an);
}}

Example
C++:

bp::tuple head_and_tail_tuple (bp::object seq)
{
    
    return bp::make_tuple(seq[0],seq[-1]);
}

Python:

$ python
>>> import objects
>>> t1 = ("Ali", "Baidu", "Tencent", "Google")
>>> t2 = objects.head_and_tail_tuple(t1)
>>> print(t2)
('Ali', 'Google')


str class

str class Simulated Python built-in str String method of type . It's defined in <boost/python/str.hpp> in , The functions provided are as follows :

namespace boost {
     namespace python
{
    
  class str : public object
  {
    
   public:
      //  Constructors 
      str(); // new str
      str(char const* s); // new str
      str(char const* start, char const* finish); // new str
      str(char const* start, std::size_t length); // new str
      template <class T>
      explicit str(T const& other);

      //  Convert the first character of the string to uppercase 
      str capitalize() const;

      //  Returns a specified width  width  Centered string 
      template <class T>
      str center(T const& width) const;

      //  return  sub  Number of occurrences ,start  and  end Indicates the specified range 
      template<class T>
      long count(T const& sub) const;
      template<class T1, class T2>
      long count(T1 const& sub,T2 const& start) const;
      template<class T1, class T2, class T3>
      long count(T1 const& sub,T2 const& start, T3 const& end) const;

      //  Yes  str  decode 
      object decode() const;
      template<class T>
      object decode(T const& encoding) const;
      template<class T1, class T2>
      object decode(T1 const& encoding, T2 const& errors) const;

      //  Yes  str  Encoding 
      object encode() const;
      template <class T>
      object encode(T const& encoding) const;
      template <class T1, class T2>
      object encode(T1 const& encoding, T2 const& errors) const;

      //  Check whether the string uses  suffix  end , among  start  and  end  Represents the string range 
      template <class T>
      bool endswith(T const& suffix) const;
      template <class T1, class T2>
      bool endswith(T1 const& suffix, T2 const& start) const;
      template <class T1, class T2, class T3>
      bool endswith(T1 const& suffix, T2 const& start, T3 const& end) const;

      //  Put... In the string  tab  Turn the symbol into a space ,tabsize  Indicates the number of spaces , The default is 8
      str expandtabs() const;
      template <class T>
      str expandtabs(T const& tabsize) const;

      //  Find... From the string  sub  Substring , among  start  and  end  Represents the string range 
      template <class T>
      long find(T const& sub) const;
      template <class T1, class T2>
      long find(T1 const& sub, T2 const& start) const;
      template <class T1, class T2, class T3>
      long find(T1 const& sub, T2 const& start, T3 const& end) const;

      //  Follow find() The method is the same , Just if  sub  Not in the string will report an exception .
      template <class T>
      long index(T const& sub) const;
      template <class T1, class T2>
      long index(T1 const& sub, T2 const& start) const;
      template <class T1, class T2, class T3>
      long index(T1 const& sub, T2 const& start, T3 const& end) const;

      //  If the string  [...]  Then return to  True,  Otherwise return to  False
      bool isalnum() const;    // [ At least one character and all characters are letters or numbers ]
      bool isalpha() const;    // [ There is at least one character and all characters are letters or Chinese characters ]
      bool isdigit() const;    // [ Numbers only ]
      bool islower() const;    // [ Contains at least one case sensitive character , And all of this ( case-sensitive ) All characters are lowercase ]
      bool isspace() const;    // [ Contains only white space ]
      bool istitle() const;    // [ It's titled ]
      bool isupper() const;    // [ Contains at least one case sensitive character , And all of this ( case-sensitive ) All characters are uppercase ]

      //  Use the specified string as the separator , take  sequence  All the elements in ( String representation of ) Merge into a new string 
      template <class T>
      str join(T const& sequence) const;

      //  Returns an original string left aligned , And fill it with Spaces to length  width  New string of .
      template <class T>
      str ljust(T const& width) const;
      
      //  Convert all uppercase characters in the string to lowercase .
      str lower() const;
      
      //  Truncates the space to the left of the string or specifies the character .
      str lstrip() const;

      //  In the string  old  Replace with  new_, If  maxsplit  Appoint , The substitution does not exceed  maxsplit  Time .
      template <class T1, class T2>
      str replace(T1 const& old, T2 const& new_) const;
      template <class T1, class T2, class T3>
      str replace(T1 const& old, T2 const& new_, T3 const& maxsplit) const;

      //  Be similar to  find(), It's just from the right .
      template <class T>
      long rfind(T const& sub) const;
      template <class T1, class T2>
      long rfind(T1 const& sub, T2 const& start) const;
      template <class T1, class T2, class T3>
      long rfind(T1 const& sub, T2 const& start, T3 const& end) const;

      //  Be similar to  index(), It's just from the right .
      template <class T>
      long rindex(T const& sub) const;
      template <class T1, class T2>
      long rindex(T1 const& sub, T2 const& start) const;
      template <class T1, class T2, class T3>
      long rindex(T1 const& sub, T2 const& start, T3 const& end) const;

      //  Returns an original string to the right , And fill to length with default spaces  width  New string of 
      template <class T>
      str rjust(T const& width) const;
    
      //  Delete the space at the end of the string or the specified character .
      str rstrip() const;

      //  With  sep  Or the space is used as the separator to intercept the string , If  maxsplit  There is a specified value , Only intercept  maxsplit+1  Substring 
      list split() const;
      template <class T>
      list split(T const& sep) const;
      template <class T1, class T2>
      list split(T1 const& sep, T2 const& maxsplit) const;

      //  Follow the line ('\r', '\r\n', \n') Separate , Returns a list of rows as elements , If parameters  keepends  by  False, Does not contain line breaks , If  True, Keep the newline .
      list splitlines() const;
      template <class T>
      list splitlines(T const& keepends) const;

      //  Check if the string is to specify a substring  prefix  start , Yes, go back to  True, Otherwise return to  False. If start  and  end  Specify the value , Check... Within the specified range .
      template <class T>
      bool startswith(T const& prefix) const;
      template <class T1, class T2>
      bool startswidth(T1 const& prefix, T2 const& start) const;
      template <class T1, class T2, class T3>
      bool startswidth(T1 const& prefix, T2 const& start, T3 const& end) const;

      str strip() const;      //  Execute... On a string  lstrip() and  rstrip()
      str swapcase() const;   //  Convert upper case to lower case in string , Lower case to upper case 
      str title() const;      //  return " The title is changed " String , That means all words begin with a capital letter , The rest of the letters are lowercase 

      //  according to  table  The table given ( contain  256  Characters ) transformation  string  The characters of ,  Put the filtered characters in  deletechars  Parameters in 
      template <class T>
      str translate(T const& table) const;
      template <class T1, class T2>
      str translate(T1 const& table, T2 const& deletechars) const;

      str upper() const;  //  Convert the lowercase letters in the string to uppercase 
  };
}}

As can be seen from the above definition ,Boost.Python str The functions given by class are similar to Python The native methods of are one-to-one correspondence , But also note that there is still no Python Native methods are flexible , For example, some functions lack some parameters , and zfill() and isdecimal() And other methods are not included .

Example
C++:

bp::str set_str_as_title (bp::str x)
{
    
    return x.title();
}

Python:

$ python
>>> import objects
>>> s = "boost wrap str class"
>>> objects.set_str_as_title(s)
'Boost Wrap Str Class'


long class

For numbers ,C++ and Python It's basically universal , and Python There are no additional methods for this data type , from long The definition of does not see any member functions .<boost/python/long.hpp>

namespace boost {
     namespace python
{
    
  class long_ : public object
  {
    
   public:
      long_(); // new long_

      template <class T>
      explicit long_(T const& rhs);

      template <class T, class U>
      long_(T const& rhs, U const& base);
  };
}}

Example
about long class Type and direct use int What's the difference in function , So far, I don't know much about .
See the following example :

namespace bp = boost::python;
int multile_int (int x)
{
    
    return x * 2;
}

bp::long_ multile_long (bp::long_ x)
{
    
    int y = bp::extract<int>(x);
    bp::long_ z(y*2);
    
    return z;
}

def("multile_int", multile_int, args("x"), return_value_policy<return_by_value>());
def("multile_long", multile_long, args("x"), return_value_policy<return_by_value>());

For the same Python Parameters , The return value is the same :

>>> import objects
>>> objects.multile_int(2)
4
>>> objects.multile_long(2)
4

But it should be noted that in the above example multile_int() Inside x And the return value is a numeric value , stay C++ The program can be printed directly . And in the multile_long() Inside z Is an instance of a class . Although finally passed to python The value will be copied in , But in C++ It cannot be directly operated as a numerical value in the program .

enum class

although Python No enum type , But as a C++ Basic data types for , It is very common in the process of software development . When you encounter this type , We often want to regard it as int Pass to Python. Boost.Python Enumeration tools are also provided , At the same time, be responsible for Python Dynamic type to C++ The correct conversion of strong static types ( stay C++ in ,int Cannot be implicitly converted to enumeration ).

This class is defined in <boost/python/enum.hpp> in . The header file defines the user to Python Open its C++ Interface of enumeration type . Its class is defined as follows :

namespace boost {
     namespace python
{
    
  template <class T>
  class enum_ : public object
  {
    
    enum_(char const* name, char const* doc = 0);    //  Constructors 
    enum_<T>& value(char const* name, T x); //  take  x  Value and  name  binding , Setting the  name  The value is  x. Return the class instance itself , namely  *this
    enum_<T>& export_values();  //  Expose the currently defined enumeration values and names , After that, the attribute name can be displayed in  Python  You can use .
  };
}}

Create one derived from Python Of int Type of Python class , The type is the same as the one passed as its first argument C++ Associated with type .

enum The use of is different from other derived classes , To illustrate , Given a C++ enumeration :

enum choice {
     red, blue };

You need to specify the constructor and bind the name and value :

enum_<choice>("choice")
    .value("red", red)
    .value("blue", blue)
    ;

after choice And its elements can be exposed to Python. We can do it in Python Access these values in :

>>> my_module.choice.red
my_module.choice.red

among my_module Is a module that declares enumeration . You can also create a new scope around a class :

scope in_X = class_<X>("X")
                .def( ... )
                .def( ... )
            ;

// Expose X::nested as X.nested
enum_<X::nested>("nested")
    .value("red", red)
    .value("blue", blue)
    ;

The new enumeration type is in the current scope() Created in the , It is usually the current module . The above code snippet creates a code derived from Python Of int Type of Python class , The type is the same as the one passed as its first argument C++ Associated with type .

notes :scope Is a global with association Python The class of the object , This object controls Python Namespace , The new class and the extended class will be defined as . The specific description is more detailed later .

Example
C++:

#include <boost/python/enum.hpp>
#include <boost/python/def.hpp>
#include <boost/python/module.hpp>

using namespace boost::python;

enum color {
     red = 1, green = 2, blue = 4 };

color identity_(color x) {
     return x; }

BOOST_PYTHON_MODULE(enums)
{
    
  enum_<color>("color")
    .value("red", red)
    .value("green", green)
    .export_values()
    .value("blue", blue)
    ;

  def("identity", identity_);
}

Python:

>>> from enums import *

>>> identity(red)
enums.color.red

>>> identity(color.red)
enums.color.red

>>> identity(green)
enums.color.green

>>> identity(color.green)
enums.color.green

>>> identity(blue)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
NameError: name 'blue' is not defined

>>> identity(color.blue)
enums.color.blue

>>> identity(color(1))
enums.color.red

>>> identity(color(2))
enums.color.green

>>> identity(color(3))
enums.color(3)

>>> identity(color(4))
enums.color.blue

>>> identity(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: bad argument type for built-in operation

Note that the above Line15 and Line3/9 The difference between , stay Python It can be used directly in the program “red”, “green” As a parameter , and “blue” no way . This is because in the previous constructor , export_values() Ahead scope Contains only “red” and “green” Two values .


Reference material

ObjectWrapper
Object Interface
Chapter 3. Object Wrappers
boost.python object
boost.python list

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

Random recommended