pybind11 Eigen + STL Containers + Numpy

本文详细介绍了如何在Pybind11中使用Eigen矩阵库和STL容器与Python进行交互,包括智能指针、容器的透明处理、Opaque类的使用,以及Eigen类型在Python和C++间的转换。同时讨论了Numpy数组的Dtype以及在Pybind11中的操作方式。

Pybind11

梳理一下 Pybind11 中 Eigen 和 STL 容器与 Python 交互的方式。需要先了解Functions章节中关于返回值和调用的规则。

Smart Pointers

STL 容器

Pybind11 已经自动支持 std::vector<>/std::deque<>/std::list<>/std::array<>/std::valarray<>, std::set<>/std::unordered_set<>, and std::map<>/std::unordered_map<> 和 Python list, set and dict 之间的转换。引用头文件 pybind11/pybind11.h 即可。如果想使用全部类,可以引用 pybind11/stl.h

Arbitrary nesting of any of these types is possible. 比如 std::vector<std::vector<int>>

问题

该方法的缺点在于每一次在 C++ 和 Python 之间转换时都要隐式转换,并且制作一份拷贝。所以下面的例子会失效

# Example 1
# C++
void append_1(std::vector<int> &v) {
   v.push_back(1);
}

# python
>>> v = [5, 6]
>>> append_1(v)
>>> print(v)
[5, 6]

# Example 2
# C++
/* ... definition ... */

class MyClass {
    std::vector<int> contents;
};

/* ... binding code ... */

py::class_<MyClass>(m, "MyClass")
    .def(py::init<>())
    .def_readwrite("contents", &MyClass::contents);
    
# Python
>>> m = MyClass()
>>> m.contents = [5, 6]
>>> print(m.contents)
[5, 6]
>>> m.contents.append(7)
>>> print(m.contents)
[5, 6]

上述例子 1 中,Python 向 C++ 传递 List 后,C++ 端制作了一份拷贝,所以两者使用的是不同的数据;例子 2 中,虽然pybind11将类的属性绑定到 Python,在 Python 端能够直接访问,但是例如 append 方法无法正常使用也是相同的原因。(Python 侧和 Cpp 侧并不是相同的实例)

Opaque 类

为了解决上述问题,Pybind11 提供了 PYBIND11_MAKE_OPAQUE(T) 宏定义将其变为 Opaque Type。Opaque Types 需要有对应的 class_ 声明。例如:

// Opaque Type declaration
PYBIND11_MAKE_OPAQUE(std::vector<int>);

// Pybind11 Class
// 定义其需要暴露给 Python 的方法
py::class_<std::vector<int>>(m, "IntVector")
    .def(py::init<>())
    .def("clear", &std::vector<int>::clear)
    .def("pop_back", &std::vector<int>::pop_back)
    .def("__len__", [](const std::
### 问题分析 CMake 在配置项目时无法找到 `eigen_stl_containers` 包的配置文件(如 `eigen_stl_containersConfig.cmake` 或 `eigen_stl_containers-config.cmake`),通常意味着系统中未安装该包,或者其路径未被正确添加至 CMake 的查找路径中。这种问题在使用 ROS 相关功能包时较为常见,尤其是在依赖链中包含第三方库或非标准消息类型的情况下[^1]。 --- ### 解决方案 1. **确认是否已安装 `eigen_stl_containers` 包** 如果尚未安装该包,可以通过 APT 安装对应的 ROS 功能包。以 ROS Noetic 为例,执行以下命令: ```bash sudo apt-get install ros-noetic-eigen-stl-containers ``` 不同 ROS 发行版对应的包名略有不同,例如: - ROS Melodic: `ros-melodic-eigen-stl-containers` - ROS Kinetic: `ros-kinetic-eigen-stl-containers` 2. **从源码安装 `eigen_stl_containers`** 如果当前发行版未提供预编译版本,可以从 GitHub 获取源码并手动安装: ```bash cd ~/ros_catkin_ws/src git clone https://github.com/ros/eigen_stl_containers.git cd .. ./src/catkin/bin/catkin_make_isolated --install -DCMAKE_BUILD_TYPE=Release --pkg eigen_stl_containers ``` 上述操作将克隆仓库并构建指定包,适用于需要自定义构建环境的情况[^2]。 3. **检查环境变量和路径设置** 确保当前 shell 环境中已加载 ROS 的设置脚本,例如: ```bash source /opt/ros/noetic/setup.bash ``` 如果使用了自定义工作空间,也应确保该工作空间已被正确 sourced,以便包含所有依赖路径。 4. **手动添加路径至 `CMAKE_PREFIX_PATH`** 若 `eigen_stl_containers` 已安装但未被识别,可尝试将其安装路径加入 `CMAKE_PREFIX_PATH`: ```bash export CMAKE_PREFIX_PATH=/opt/ros/noetic:$CMAKE_PREFIX_PATH ``` 5. **验证 `CMakeLists.txt` 和 `package.xml` 文件** 确保 `CMakeLists.txt` 中包含对 `eigen_stl_containers` 的正确依赖声明: ```cmake find_package(catkin REQUIRED COMPONENTS ... eigen_stl_containers ... ) ``` 同时,在 `package.xml` 中也应包含如下内容: ```xml <depend>eigen_stl_containers</depend> ``` 6. **处理依赖冲突或缺失的开发包** 某些情况下,即使功能包已安装,若缺少相应的开发文件(如头文件、配置文件等),CMake 仍可能报错。此时应检查是否安装了完整的开发包,例如: ```bash sudo apt-get install libeigen3-dev ``` --- ### 示例代码片段 ```bash # 安装 eigen_stl_containers(以 ROS Noetic 为例) sudo apt-get install ros-noetic-eigen-stl-containers # 手动添加路径至 CMAKE_PREFIX_PATH export CMAKE_PREFIX_PATH=/opt/ros/noetic:$CMAKE_PREFIX_PATH # 从源码安装 eigen_stl_containers cd ~/ros_catkin_ws/src git clone https://github.com/ros/eigen_stl_containers.git cd .. ./src/catkin/bin/catkin_make_isolated --install -DCMAKE_BUILD_TYPE=Release --pkg eigen_stl_containers ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值