Pybind11类型转换
Pybind11帮助我们方便的实现C++和Python之间的调用,无论是相互的接口暴露还是数据传递都要求我们正确的在C++和Python类型之间进行转换(官方文档)。
三种场景
- C++原生类型暴露给python
- Python原生类型暴露给C++
- C++和Python原生类型间相互转换
C++原生类型暴露给Python
使用py::class_
将自定义的C++类型暴露给Python(参考这里)。C++类型传递给Python时会在原生C++类型外加一层wrapper,从Python取回时只用去掉wrapper即可。
Python原生类型暴露给C++
在C++中取用Python的原生类型(例如:tuple
、list
),例如:
1 | // C++中使用Python对象 |
Python中传入Python对象给C++:
1 | 1, 2, 3]) print_list([ |
这个例子里Python中的list
类型没有进行任何转换,只是被封装进了C++的py::list
类中。目前Pybind11支持以下类型(参考这里):handle
, object
, bool_
, int_
, float_
, str
, bytes
, tuple
, list
, dict
, slice
, none
, capsule
, iterable
, iterator
, function
, buffer
, array
, array_t
。
C++和Python原生类型间相互转换
有些场景C++和Python都用的是各自的原生类型,Pybind11支持常见C++原生类型和Python原生类型间的相互转换,例如:
1 | void print_vector(const std::vector<int> &v) { |
Python中调用:
1 | >>> print_vector([1, 2, 3]) |
容易注意到Python中传入的为list
类型,而C++中处理的类型为const std::vector<int> &
。Pybind11这种默认类型转换会在原生类型间拷贝数据,例如上面Python中的调用会首先将list中的数据拷贝到一个std::vector<int>
中,然后进行C++中的调用。
NOTE: 默认的拷贝可能开销很大,可以通过手写opaque types重载类型转换的wrapper来避免不必要的拷贝。opaque types还没有使用过,有机会单独挖坑写。
STL库
Pybind11默认(pybind11/pybind11.h
)支持std::pair<>
,std::tuple<>
和list
, set
, dict
之间的自动转换。引入pybind11/stl.h
可以新增std::vector<>
, std::deque<>
, std::list<>
, std::array<>
, std::set<>
, std::unordered_set<>
, std::map<>
和std::unordered_map<>
的与Python的自动转换。
绑定STL容器
pybind11/stl_bind.h
可以帮助我们将STL容器作为原生对象暴露出来。例如:
1 |
|