pybind11使用教程筆記__4_數據類型轉換(typeconversion)

Type conversions 類型轉換

除了實現 python和C++的函數調用,兩種語言之間的數據類型轉換也很重要。通常有三種實現方法。

  • 在程序的所有地方均使用C++的數據類型,這樣的話相應的類型必須進行打包,這樣纔可以在python中進行調用。
  • 在程序的所有地方均使用python的數據類型,這樣的話相應的類型必須進行打包,這樣纔可以在C++中進行調用。
  • 在C++程序中使用C++的數據類型,在python中使用python的數據類型。(pybind11 推薦

type conversion 使用起來最自然,在各自的語言中使用原生的數據類型。但是這種方法的劣勢是python和C++之間的相互調用數據必須要拷貝數據,因爲相同的數據類型在python和C++中memory layout會有區別。

overview

  1. Native type in C++, wrapper in Python

    使用 py::class_來將C++數據類型打包給python使用,具體見 Object-oriented code section。 底層的數據結構是C++原生的數據結構, py::class_ wrapper 提供了一個python使用的接口。

    對於一個object-like的數據類型,python使用時pybind11會自動給C++原生的數據結構添加外圍warper。當從python中將數據取回到C++中時,會自動去掉外層的warper。

  2. Wrapper in C++, native type in Python
    和上面的情況正好相反,這種情況主要利用python的原生數據類型,比如tuple和list。主要可以通過py::object warper 系列使C++能夠使用python的原生數據類型。更多細節見: Python types section, 如下是一個簡單的例子:

    void print_list(py::list my_list) {
        for (auto item : my_list)
            std::cout << item << " ";
    }
    
    >>> print_list([1, 2, 3])
    1 2 3
    

    上例中,python的數據類型list的數據格式沒有被轉變,只是在C++中使用 py::list class 將其包裹,其內核仍然是python的object。對py::list 對象進行copy 會像在python中一樣做一個counting-reference的操作。將py::list 對象返回給python只需要將對象外邊包裹的代碼去除掉就可以了。

  3. Converting between native C++ and Python types
    在C++和python中各自使用各自的原生數據類型,交互時對各自原生的數據類型進行轉換。

    void print_vector(const std::vector<int> &v) {
        for (auto item : v)
            std::cout << item << "\n";
    }
    
    >>> print_vector([1, 2, 3])
    1 2 3
    

    這種情況下,pybind11 會在C++中構建一個新的new std::vector<int> ,並從python 的list 中copy每個元素。新構建的std::vector會被傳入到print_vector()中。在C++到python的數據流中,會發生類似的操作,python會創建一個list對象以匹配C++返回的數據。
    很多類似的數據類型轉換都是支持的,而且都是開包即用,如下表所示。這些數據類型轉換非常方便,但是都需要copy數據。對於 small immutable types ,這樣的方式挺好的,但是對於非常大的數據結構,copy數據的開銷會非常大。可以通過手動添加warper代碼的方式來避免這樣的開銷,需要花一些精力,這方面更多細節見 Making opaque types section.

List of all builtin conversions

如下數據類型可以直接進行數據類型轉換。如需轉換其他數據類型,見binding Object-oriented code.

Data type Description Header file
int8_t, uint8_t 8-bit integers pybind11/pybind11.h
int16_t, uint16_t 16-bit integers pybind11/pybind11.h
int32_t, uint32_t 32-bit integers pybind11/pybind11.h
int64_t, uint64_t 64-bit integers pybind11/pybind11.h
ssize_t, size_t Platform-dependent size pybind11/pybind11.h
float, double Floating point types pybind11/pybind11.h
bool Two-state Boolean type pybind11/pybind11.h
char Character literal pybind11/pybind11.h
char16_t UTF-16 character literal pybind11/pybind11.h
char32_t UTF-32 character literal pybind11/pybind11.h
wchar_t Wide character literal pybind11/pybind11.h
const char * UTF-8 string literal pybind11/pybind11.h
const char16_t * UTF-16 string literal pybind11/pybind11.h
const char32_t * UTF-32 string literal pybind11/pybind11.h
const wchar_t * Wide string literal pybind11/pybind11.h
std::string STL dynamic UTF-8 string pybind11/pybind11.h
std::u16string STL dynamic UTF-16 string pybind11/pybind11.h
std::u32string STL dynamic UTF-32 string pybind11/pybind11.h
std::wstring STL dynamic wide string pybind11/pybind11.h
std::string_view, std::u16string_view, etc. STL C++17 string views pybind11/pybind11.h
std::pair<T1, T2> Pair of two custom types pybind11/pybind11.h
std::tuple<…> Arbitrary tuple of types pybind11/pybind11.h
std::reference_wrapper<…> Reference type wrapper pybind11/pybind11.h
std::complex Complex numbers pybind11/complex.h
std::array<T, Size> STL static array pybind11/stl.h
std::vector STL dynamic array pybind11/stl.h
std::deque STL double-ended queue pybind11/stl.h
std::valarray STL value array pybind11/stl.h
std::list STL linked list pybind11/stl.h
std::map<T1, T2> STL ordered map pybind11/stl.h
std::unordered_map<T1, T2> STL unordered map pybind11/stl.h
std::set STL ordered set pybind11/stl.h
std::unordered_set STL unordered set pybind11/stl.h
std::optional STL optional type (C++17) pybind11/stl.h
std::experimental::optional STL optional type (exp.) pybind11/stl.h
std::variant<…> Type-safe union (C++17) pybind11/stl.h
std::function<…> STL polymorphic function pybind11/functional.h
std::chrono::duration<…> STL time duration pybind11/chrono.h
std::chrono::time_point<…> STL date/time pybind11/chrono.h
Eigen::Matrix<…> Eigen: dense matrix pybind11/eigen.h
Eigen::Map<…> Eigen: mapped memory pybind11/eigen.h
Eigen::SparseMatrix<…> Eigen: sparse matrix pybind11/eigen.h
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章