我有一个 C++ 中的单例类(没有公共构造函数,C++ 程序员调用 class.instance() 来创建单例或返回现有的单例)。
我更愿意在 Python 级别隐藏它。如果我正在编写一个 Python 单例,我会在__new__. 如果一个类没有公共构造函数,我认为我无法创建__init__包装器(我的尝试失败了)。我在 pybind11 文档中没有看到提及__new__(尽管可能错过了它,并且 Google 似乎很乐意省略下划线包含“new”的返回页面,但没有提及__new__)。
pybind11(甚至Boost.Python)有单例配方吗?
PyBind11 文档讨论了使用enum here。
显示的示例假定枚举嵌入在一个类中,如下所示:
struct Pet {
enum Kind {
Dog = 0,
Cat
};
Pet(const std::string &name, Kind type) : name(name), type(type) { }
std::string name;
Kind type;
};
py::class_<Pet> pet(m, "Pet");
pet.def(py::init<const std::string &, Pet::Kind>())
.def_readwrite("name", &Pet::name)
.def_readwrite("type", &Pet::type);
py::enum_<Pet::Kind>(pet, "Kind")
.value("Dog", Pet::Kind::Dog)
.value("Cat", Pet::Kind::Cat)
.export_values();
Run Code Online (Sandbox Code Playgroud)
我的情况不同。我有一个全局enum变量,它的值用于改变几个函数的行为。
enum ModeType {
COMPLETE,
PARTIAL,
SPECIAL
};
std::vector<int> Munger(
std::vector<int> &data,
ModeType mode
){
//...
}
Run Code Online (Sandbox Code Playgroud)
我试图像这样注册它:
PYBIND11_MODULE(_mlib, m) {
py::enum_<ModeType>(m, "ModeType")
.value("COMPLETE", ModeType::COMPLETE )
.value("PARTIAL", ModeType::PARTIAL …Run Code Online (Sandbox Code Playgroud) 根据 pybind11 文档https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html:
当包含额外的头文件 pybind11/stl.h 时,std::vector<>/std::list<>/std::array<>、std::set<>/std::unordered_set<> 和 std::set<>/std::unordered_set<> 之间的转换自动启用 std::map<>/std::unordered_map<> 和 Python 列表、集合和字典数据结构。
但是,我终其一生都无法让它发挥作用。我想我误解了一些东西,所以我希望有人可以为我澄清。
这是我期望的工作:
// Test
std::vector<double> test_vec{1,2,3,4,5};
py::list test_list = test_vec;
py::list test_list2(test_vec);
py::list test_list3 = py::cast<py::list>(test_vec);
Run Code Online (Sandbox Code Playgroud)
以下是错误:
error: conversion from ‘std::vector<double>’ to non-scalar type ‘pybind11::list’ requested
py::list test_list = test_vec;
error: no matching function for call to ‘pybind11::list::list(std::vector<double>&)’
py::list test_list2(test_vec);
error: no matching function for call to ‘cast(std::vector<double>&)’
py::list test_list3 = py::cast<py::list>(test_vec)
Run Code Online (Sandbox Code Playgroud)
文档说要查看tests/test_stl.cpp这应该如何工作的示例,但是我担心我无法破译该文件中发生的事情。
我有一个返回 a 的 C++ 函数,std::vector并且使用 Pybind11,我想将该向量的内容作为 Numpy 数组返回,而不必将向量的基础数据复制到原始数据数组中。
当前尝试
在这个写得很好的 SO 答案中,作者演示了如何确保在 Numpy 数组的引用计数为零时适当地释放在 C++ 中创建的原始数据数组。我尝试使用以下方法编写此版本std::vector:
// aside - I made a templated version of the wrapper with which
// I create specific instances of in the PYBIND11_MODULE definitions:
//
// m.def("my_func", &wrapper<int>, ...)
// m.def("my_func", &wrapper<float>, ...)
//
template <typename T>
py::array_t<T> wrapper(py::array_t<T> input) {
auto proxy = input.template unchecked<1>();
std::vector<T> result = compute_something_returns_vector(proxy);
// give memory cleanup responsibility to the Numpy array …Run Code Online (Sandbox Code Playgroud) 我正在尝试为需要使用支持 cuda 的编译器进行编译的虚拟类生成 python 绑定。我正在使用 cmake 3.12.0、pybind11 v2.2.3 和 nvcc 7.5.17。编译失败,因为 和 等选项-flto直接-fno-fat-lto-objects传递给 nvcc,而 nvcc 无法识别它们。
这是一个(最小)示例:
Cuda 代码:
//Adder.hpp
#include <thrust/host_vector.h>
struct Adder {
thrust::host_vector<float> a_h;
thrust::host_vector<float> b_h;
thrust::host_vector<float> r_h;
int N;
Adder(int N);
void set_a(float const * const in);
void set_b(float const * const in);
void calc();
void calc_gpu();
};
//Adder.cu
#include "Adder.hpp"
#include <thrust/device_vector.h>
Adder::Adder(int N): N(N),a_h(N),b_h(N),r_h(N) {}
void Adder::set_a(float const * const in) {
for (int i=0; i<N; ++i) {
a_h[i] = …Run Code Online (Sandbox Code Playgroud) 我从我的项目文档中看到我需要python-pybind11使用安装
sudo apt -y install python-pybind11
Run Code Online (Sandbox Code Playgroud)
但我收到这样的错误:
正在阅读包裹清单...完成
构建依赖树
读取状态信息...完成E:无法找到包 python-pybind11
我不确定python-pybind11包裹是否有效,在哪里可以检查?
我的最终目标是从我的 C++ 代码编译 Python C++ 扩展。目前,为了开始使用,我将遵循文档第一步中的一个简单示例pybind11。我的工作环境是 Windows 7 Professional 64 位、mingw-w64 (x86_64-8.1.0-posix-seh-rt_v6-rev0) 和 Anaconda3 with Python 3.7.4 64 位。我有2个文件。第一个是 C++ 文件——example.cpp
#include <pybind11/pybind11.h>
int add(int i, int j) {
return i + j;
}
PYBIND11_MODULE(example, m) {
m.doc() = "pybind11 example plugin"; // optional module docstring
m.def("add", &add, "A function which adds two numbers");
}
Run Code Online (Sandbox Code Playgroud)
我使用以下命令编译 C++ 文件:
C:/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/g++.exe -shared -std=c++11 -DMS_WIN64 -fPIC -ID:\Users\ADAS\anaconda3\Include -ID:\Users\ADAS\anaconda3\Library\include -ID:\Users\ADAS\anaconda3\pkgs\python-3.7.4-h5263a28_0\include -Wall -LD:\Users\ADAS\anaconda3\Lib -LD:\Users\ADAS\anaconda3\pkgs\python-3.7.4-h5263a28_0\libs example.cpp -o example.dll -lPython37
Run Code Online (Sandbox Code Playgroud)
编译结果成功,正在获取example.dll文件。
在下一步中,我运行以下 …
目前我正在尝试将 a 转换py::dict为其对应的C++s std::map。尝试像这样使用自动转换失败:
#include <pybind11/stl.h>
namespace py = pybind11;
using namespace py::literals;
...
py::dict py_kwargs = py::dict("number1"_a = 5, "number2"_a = 42);
auto cpp_kwargs = py_kwargs.cast<std::map<int, int>>();
Run Code Online (Sandbox Code Playgroud)
但有一个例外:
Unable to cast Python instance of type <class 'dict'> to C++ type 'std::map<int,int,std::less<int>,std::allocator<std::pair<int const ,int> > >'
Run Code Online (Sandbox Code Playgroud)
我在这里缺少什么?
另外,我应该如何处理 python 字典具有不同键类型的情况,例如:
Unable to cast Python instance of type <class 'dict'> to C++ type 'std::map<int,int,std::less<int>,std::allocator<std::pair<int const ,int> > >'
Run Code Online (Sandbox Code Playgroud)
在这种情况下我应该如何进行转换?
pybind11 文档总体来说不错,但它的一个方面不是解释安装过程以及使用 cmake 获取和运行示例的过程。
我已经设法弄清楚如何获取和构建示例。但这会带来更多问题。几乎所有示例都依赖于将 pybind11 存储库下载到示例文件夹中,并在 cmake 运行中包含存储库的根文件夹(根文件夹包含 cmakelists.txt 文件)。该存储库的内容与使用 pip 或 conda 安装 pybind11 时添加到 python 环境的内容有很多共同点。但文件夹组织完全不同。
所以我很好奇:
一般来说,我对不理解这些事情的“如何运作”方面感到非常不舒服,所以这对我真的很有帮助。
我正在尝试为OpenVSlam项目生成 Python 绑定。
我正在使用 PyBind11 并遵循cmake_example模板。
我在我的开发环境中成功构建了该.so文件pybind11_add_module,其中安装了所有依赖项(例如 OpenCV、Protobuf 等库)。该.so文件在此开发环境中运行良好。我可以正确运行import sys; sys.path.append('.'); import openvslam_python;和使用绑定函数。但是,我想将该.so文件作为 Python 包发送。
问题是,当我运行python3 setup.py sdist bdist_wheel并尝试wheel在另一个环境(没有安装的依赖项)上安装结果时,它说找不到依赖项的.so文件。例如,它输出以下错误(在 Docker 容器中):
>>> import sys
>>> sys.path.append('.')
>>> import openvslam_python
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: libopenvslam.so: cannot open shared object file: No such file or directory
Run Code Online (Sandbox Code Playgroud)
我想知道是否有一种方法将 PyBind11 绑定的依赖项与 CMake(或者可能在脚本内setup.py)捆绑在一起,以便能够在没有安装任何依赖项的环境中安装它们。这样,我可以使用简单的pip install …