current position:Home>Boost (5): extract the type of C + + language and extract class from Python object

Boost (5): extract the type of C + + language and extract class from Python object

2022-05-15 06:01:57Xiangdi

Preface

python and c++ The difference between data types is a common problem in conversion , Some simple data types can be generalized , But there are many types that cannot be used directly . When faced with such problems ,boost.python Provided extract Class is a convenient solution . This article is used to record my understanding of extract The understanding of the .

1. explain

1.1 Extract Introduce

Extract yes Boost.Python Used from Python Object c++ The class of the object , Through this class, we can put some Python The object of is converted to C++ The object of language . Such as the boost::python::str A variable of type is converted to char * Type variable .

Extract The executive member of must be a non overloaded static function , Its single parameter is Python object type . Acceptable Python Object types include from PyObject The derived ones are public ( And clear ) Object type of , As well as PyObject Layout compatible POD type .

notes : If you want to python Object c++ type , Then the object must first contain this type of content .

1.2 Usage method

Here are some basic ways to use .
1. obtain python The value of the object

int a = boost::python::extract<int>(x)

from python object x Extract from int The content of .


2. Check with the constructor before extraction

int g(object x)
{
    
    extract<int> get_int(x);
    if (get_int.check())
        return get_int();
    else
        return 0;
}

Constructors get_int First call check() To check if you can x convert to int Data of type .


3. Use extract Directly modify variable objects
We can use extract Without copying the target object , Direct and convenient modification boost::python::object And its derived types PyObject*.

namespace bp = boost::python;

// bp::object x;
dict d = bp::extract<bp::dict>(x.attr("__dict__"));
d["whatever"] = 3;          // modifies x.__dict__ !

// PyObject* pyobj;
PyObject* __dict__ = PyObject_GetAttrString(pyobj, const_cast<char*>("__dict__"));
// (see also http://article.gmane.org/gmane.comp.python.c%2B%2B/15664)
bp::dict dictobj = bp::extract<bp::dict>(__dict__);
dictobj["whatever"] = 3;          // modifies pyobj __dict___!



4. Extract elements from more complex structures
In order to extract elements from complex structures such as lists and tuples , We must nest extraction calls . Suppose there is an element of type tuple Of list Variable , Extract from it tuple The data in .

boost::python::list l1 = [(1, 2), (3, 4), (5, 6)];

extract<int>(extract<tuple>(list[0])());


2. Example

To demonstrate , Prior to RealWorld Add a... To your class ShowRelatives() function , This function will pass in python list Type data converted to c++ Under the std::vector.

Declare and define functions

stay classes.hpp Of RealWorld Add function declaration under class :

void ShowRelatives(boost::python::list &rels);

Its definition is as follows :

void RealWorld::ShowRelatives(python::list &rels)
{
    
    std::vector<char *> rel(len(rels), 0);

    for (int i = 0; i < len(rels); i++){
    
        rel[i] = python::extract<char *> (rels[i]);
    }

    for (int i = 0; i < rel.size(); i++)
        std::cout << rel[i] << " ";
    std::cout << std::endl;
}


Added to the python modular

.def ("ShowRelatives", &RealWorld::ShowRelatives, python::args("rels"))


A simple test

python The test procedure is as follows :

#!/usr/bin/env python

import classes

t1 = classes.RealWorld("Xiangdi", 'm')
relative = ("father", "mother", "brother", "sister")
t1.ShowRelatives(relative)


Running results

notes :python list It doesn't seem to convert directly to std::vectorstd::string In the form of , Because when I try this, I always report mistakes :

Traceback (most recent call last):
  File "classes.py", line 9, in <module>
    t1.ShowRelatives(relative)
RuntimeError: basic_string::_M_construct null not valid


3. extract Class explanation

extract Class is defined in <boost/python/extract.hpp> In file .

3.1 extract Definition

template <class T>
struct extract
    : converter::select_extract<T>::type
{
    
 private:
    typedef typename converter::select_extract<T>::type base;
 public:
    typedef typename base::result_type result_type;
    
    operator result_type() const
    {
    
        return (*this)();
    }
    
    extract(PyObject*);
    extract(api::object const&);
};

among T Indicates the target to be extracted c++ type . Two usages are supported :

  • extract(o) : Generate an implicit conversion to T The temporary object of ( You can also perform explicit conversion through the function call operator of the object ). however , If o None of them can be converted into T Object of type , Will trigger Python TypeError abnormal .
  • extract x(o): This method constructs an extractor , In this extractor check() The member function asks if the transformation is available , Without throwing an exception .

3.2 Constructors

extract(PyObject*);
extract(api::object const&);

In the structure extract When an instance , You can pass in two parameters , One is Python Object pointer , The other is object reference . From the implementation of the two functions , The second method is actually to pass the pointer of the reference object to the parent object inside the function body .

3.3 Member functions

Only some member functions are introduced here .

operator result_type() const

result_type() The function is used to store python The pointer to the object is converted to T or T& type , That is, we are instantiating extractor The action that will run automatically after . If something goes wrong ( such as python Object does not contain T Type of content ), Function will trigger TypeError.

I can't see from the definition code above ,extract The parent class of also provides some additional member functions , such as check().

bool check() const;

This function is in the extract In the constructor , To examine python Whether the object can be converted to T or T& type , If you can't return false. It should be noted that even if it cannot be converted, it will not trigger python abnormal .

Reference material

boost:Extractor
Chapter 5. To/From Python Type Conversion
boost.python/extract

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

Random recommended