我正在尝试使用 pybind11 创建一个 python 绑定,该绑定引用一个 C++ 实例,该实例的内存在 C++ 端处理。这是一些示例代码:
import <pybind11/pybind11>
struct Dog {
void bark() { printf("Bark!\n"); }
};
int main()
{
auto dog = new Dog;
Py_Initialize();
initexample(); // Initialize the example python module for import
// TBD - Add binding between dog and example.dog .
PyRun_StringFlags("import example\n"
"\n"
"example.dog.bark()\n" // Access the C++ allocated object dog.
, Py_file_input, main_dict, main_dict, NULL);
Py_Finalize();
}
Run Code Online (Sandbox Code Playgroud)
example.dog我一直困惑于如何创建 python和 C++变量之间的链接dog。
我不能使用py:class_<Dog>.def(py::init<>()),因为这将分配一个新的实例Dog,这不是我想要的。
我正在尝试从包含main()使用的函数的C ++代码中调用python函数Pybind11。但是我发现很少有参考资料可用。现有的大多数文档都谈到了相反的方向,即从Python调用C ++。
有没有完整的示例说明如何执行此操作?我找到的唯一参考是:https : //github.com/pybind/pybind11/issues/30
但是它的信息很少。
我使用Python虚拟环境.基本上,它工作正常,但在编译一些Python绑定时遇到问题,即使用libIGL和pybind11.
CMake具有以下与Python相关的变量:
PYTHON_EXECUTABLE /users/me/libs/pyvenv/bin/python
PYTHON_INCLUDE_DIR /usr/include/python2.7
PYTHON_LIBRARY /usr/lib64/libpython2.7.so
Run Code Online (Sandbox Code Playgroud)
它似乎可以正确检测可执行文件,它是以前激活的虚拟环境的python3.5,但是它为包含和库找到了一些错误的2.7路径.
所以我想手动将这些路径设置到我的虚拟环境中.我浏览了虚拟环境的目录结构,我想我发现了包含在中/users/me/libs/pyvenv/include/python3.5m.但我找不到libpython*,*.so我的虚拟环境中根本没有文件.那么在那种情况下我应该使用哪个库?
当我想在Python中使用C++多态时,我对pybind11有一个奇怪的行为.这是我的问题的一个简单示例:
import polymorphism as plm
a = plm.mylist()
print(a)
a[0].print()
a[1].print()
Run Code Online (Sandbox Code Playgroud)
这个脚本的输出是
[MyBase,MyDerived]
MyBase
MyBase
但预期的产出是
[MyBase,MyDerived]
MyBase
MyDerived
因为mylist返回一个std :: vector,它包含一个派生类(MyDerived)的实例作为第二个成员.奇怪的是,当我打印整个列表时,MyDerived被识别出来.
这是C++代码的头文件:
/* polymorphism.hpp */
#ifndef POLYMORPHISM_HPP
#define POLYMORPHISM_HPP
#include <vector>
class MyBase
{
public:
virtual void print() const;
};
class MyDerived : public MyBase
{
public:
virtual void print() const;
};
std::vector<MyBase*> mylist();
#endif
Run Code Online (Sandbox Code Playgroud)
这是cpp文件:
#include "polymorphism.hpp"
#include <iostream>
#include <pybind11/stl.h>
#include <pybind11/pybind11.h>
void MyBase::print() const
{ std::cout << "MyBase" << std::endl; }
void MyDerived::print() const
{ std::cout …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包裹是否有效,在哪里可以检查?
我已经使用pybind11创建了以下类:
py::class_<Raster>(m, "Raster")
.def(py::init<double*, std::size_t, std::size_t, std::size_t, double, double, double>());
Run Code Online (Sandbox Code Playgroud)
但是我不知道如何在Python中调用此构造函数。我看到Python期望在double *位置使用浮点数,但我似乎无法调用它。
我已经尝试过,ctypes.data_as(ctypes.POINTER(ctypes.c_double))但这不起作用...
编辑:
我已经从@Sergei答案中提取了答案。
py::class_<Raster>(m, "Raster", py::buffer_protocol())
.def("__init__", [](Raster& raster, py::array_t<double> buffer, double spacingX, double spacingY, double spacingZ) {
py::buffer_info info = buffer.request();
new (&raster) Raster3D(static_cast<double*>(info.ptr), info.shape[0], info.shape[1], info.shape[2], spacingX, spacingY, spacingZ);
})
Run Code Online (Sandbox Code Playgroud) 我的最终目标是从我的 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文件。
在下一步中,我运行以下 …
我正在尝试将 python 绑定添加到中等大小的 C++ 科学代码(数万个 LOC)。我设法让它在没有太多问题的情况下工作,但我现在遇到了一个我无法解决的问题。代码组织如下:
libcommon.acore.sopython模块“主要”部分的绑定工作正常。事实上,从独立代码或从 python 启动的模拟给出了完全相同的结果。
但是,该代码还支持类似插件的系统,该系统可以在运行时加载共享库。这些共享库包含从主代码中定义的接口继承的类。事实证明,如果我尝试从 python 链接这些共享库,我会收到臭名昭著的“未定义符号”错误。我已经检查过这些符号是否在core.so模块中(使用nm -D)。事实上,使用独立代码执行动态链接的模拟工作得很好(在同一文件夹中并使用相同的输入)。不知何故,共享库在通过 python 调用时找不到正确的符号,但在由独立代码加载时没有问题。我正在使用 CMake 来构建系统。
接下来是 MCE。复制文件夹中的每个文件,pybind11在同一位置复制(或链接)文件夹并使用以下命令:
mkdir build
cd build
cmake ..
make
Run Code Online (Sandbox Code Playgroud)
这将生成一个standalone二进制文件和一个 python 模块。该standalone可执行文件将产生正确的输出。相比之下,在 python3 中使用以下命令(至少在我看来,应该是等效的)会产生错误:
mkdir build
cd build
cmake ..
make
Run Code Online (Sandbox Code Playgroud)
#include "Base.h"
#include "plugin_loader.h"
#include <iostream>
int main() {
Base *d = load_plugin();
if(d == NULL) {
std::cerr << "No lib found" << std::endl; …Run Code Online (Sandbox Code Playgroud) 目前我正在尝试将 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)
在这种情况下我应该如何进行转换?