我的main.cpp文件如下所示:
// Embeding the interpreter into c++
// https://pybind11.readthedocs.io/en/master/advanced/embedding.html
#include <pybind11/embed.h>
#include <iostream>
#include <string>
// Define namespace for pybind11
namespace py = pybind11;
class Vehiclee
{
// Access specifier
public:
// Data Members
int vehicle_id;
std::string vehicle_name;
std::string vehicle_color;
// Member Functions()
void printname()
{
std::cout << "Vehicle id is: " << vehicle_id;
std::cout << "Vehicle name is: " << vehicle_name;
std::cout << "Vehicle color is: " << vehicle_color;
}
};
int main() {
// Initialize the …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用pybind11以使第三方 C++ 库调用 Python 方法。该库是多线程的,每个线程创建一个 Python 对象,然后对该对象的方法进行多次调用。
我的问题是调用py::gil_scoped_acquire acquire;死锁。下面给出了重现该问题的最小代码。我究竟做错了什么?
// main.cpp
class Wrapper
{
public:
Wrapper()
{
py::gil_scoped_acquire acquire;
auto obj = py::module::import("main").attr("PythonClass")();
_get_x = obj.attr("get_x");
_set_x = obj.attr("set_x");
}
int get_x()
{
py::gil_scoped_acquire acquire;
return _get_x().cast<int>();
}
void set_x(int x)
{
py::gil_scoped_acquire acquire;
_set_x(x);
}
private:
py::object _get_x;
py::object _set_x;
};
void thread_func()
{
Wrapper w;
for (int i = 0; i < 10; i++)
{
w.set_x(i);
std::cout << "thread: " << std::this_thread::get_id() << " …Run Code Online (Sandbox Code Playgroud) 我正在尝试创建和分发(使用 pip)一个 Python 包,其中包含 Python 代码和使用 Pybind11(使用 Visual Studio 2019)编译为 .pyd 文件的 C++ 代码。我还想包含.pyi 存根文件,用于 VScode 和其他编辑器。我找不到太多关于正确执行此操作的文档。
我希望能够像平常一样通过 pip 安装包,并from mymodule.mysubmodule import myfunc像普通的 Python 包一样编写等,包括使用我编写的 .pyi 文件自动完成、类型注释、VScode 智能感知等。
我的 C++ 代码位于多个 cpp 和头文件中。它使用一些标准库和一些外部库(例如boost)。它定义了一个模块和 2 个子模块。我希望能够在 Windows 和 Linux 上以及 x86 和 x64 上分发它。我目前的目标是 Python 3.9 和 c++17 标准。
我应该如何构建和分发这个包?我是否包含 c++ 源文件,并创建一个类似于Pybind11 示例的 setup.py ?如果是这样,我如何包含外部库?如何构建 .pyi 存根文件?这是否意味着尝试安装我的软件包的人也需要 C++ 编译器?
或者,我应该将我的 c++ 编译为每个平台和架构的 .pyd/.so 文件吗?如果是这样,有没有办法指定通过 pip 安装哪个?再说一次,我将如何构建 .pyi 存根?
我有一个混合 C++/Python 项目。它使用pybind11包装 Python 的 C++ 代码,并使用 bazel来构建解决方案。我对这个技术栈非常满意。安装 C++ 编译器、Python 发行版和 bazel 后,bazel run命令即可下载依赖项、构建并运行整个 C++/absl/Python/numpy 集团。
但为了让用户的事情变得更简单,我想将我的代码打包为 PyPI 包,以便可以使用pip install. 我希望该包是跨平台的,可以在 Windows、Linux 和 MacOS 上运行。
在生成新版本时,建立构建、打包并将所有内容上传到 PyPI 的管道的最清晰方法是什么?
我理解 C++ 上下文中枚举和枚举类之间的区别,但是在绑定枚举和枚举类的上下文中是否有任何真正的区别?
举例来说:
enum class options {
maybe,
yes,
no,
};
enum words {
hello,
world
};
Run Code Online (Sandbox Code Playgroud)
我刚刚以相同的方式绑定它们(见下文),所以我的问题是,我是否忽略了某些东西,或者在使用 pybind11 将它们绑定到 python 的上下文中,枚举和枚举类实际上是相同的吗?
py::enum_<options>(m, "options")
.value("maybe", options::maybe)
.value("yes", options::yes)
.value("no", options::no);
py::enum_<words>(m, "words")
.value("hello", words::hello)
.value("world", words::world)
Run Code Online (Sandbox Code Playgroud) 我正在为基于 C++ 的加密方案开发一个 python 包装器,其中密钥和密文是非常大的数字(最多 2048 位)。
在 C++ 中,我使用Intel BigNumber 类来存储和处理如此大的数字。
由于 Python 本身支持通过对象“看似”无限位整数,因此我在通过 Python 将此类变量作为参数传递时遇到了麻烦。
py::class_<BigNumber>(m, "BigNumber")
.def(py::init<unsigned int>())
.def(py::init<int>())
.def(py::init<BigNumber>())
.def(py::init([](py::list data) {
size_t length = data.size();
unsigned int* pData = new unsigned int[length];
for (int i = 0; i < length; i++) {
pData[i] = data[i].cast<unsigned int>();
}
return std::unique_ptr<BigNumber>(new BigNumber(pData, length));
}))
.def(py::init([](py::array_t<unsigned int> data) {
py::buffer_info buffer_info = data.request();
unsigned int* pData = static_cast<unsigned int*>(buffer_info.ptr);
std::vector<ssize_t> shape = buffer_info.shape;
return std::unique_ptr<BigNumber>(new BigNumber(pData, …Run Code Online (Sandbox Code Playgroud) 我正在努力使最简单的示例发挥作用。这是我的代码:
// example.cpp
#include <pybind11/pybind11.h>
namespace py = pybind11;
class B {
public:
int b;
};
class A {
public:
int a;
A(int a) :a(a) {}
A(B b) { a = b.b; }
};
void fn(A) {}
PYBIND11_MODULE(example, m) {
py::class_<A>(m, "A")
.def(
py::init<int>(),
py::arg("a") = 1
);
py::class_<B>(m, "B")
.def(
py::init<int>(),
py::arg("b") = 2
);
py::implicitly_convertible<A, B>();
m.def("fn", &fn,
py::arg("a")
);
}
Run Code Online (Sandbox Code Playgroud)
# test.py
from example import *
a = A()
b = B()
fn(b)
Run Code Online (Sandbox Code Playgroud)
它构建得很好,但输出是:
$ python3.9 test.py …Run Code Online (Sandbox Code Playgroud) 我目前正在尝试定义一个共享库,我的目标是从 Python C++ 扩展以及普通 C++ 应用程序中使用它。
我设法构建了共享库,并尝试将一个简单的 C++ 应用程序链接到它以测试其功能,但共享库的函数之一被链接器视为未定义的引用。检查后nm --demangle --dynamic --defined-only --extern-only libmylib.so,我意识到该函数没有被共享库导出,但我不知道为什么。
该函数的签名如下:
void bootstrap_mylib(std::vector<std::string> python_path,
std::vector<std::string> python_scripts,
std::string interface_module,
std::function<void (pybind11::module_, pybind11::object)> interface_module_initializer);
Run Code Online (Sandbox Code Playgroud)
如果我注释掉最后一个参数,一切都会顺利,所以问题似乎来自于我以某种方式声明与 pybind11 的依赖关系的方式。
以下是我的 CMakeLists.txt 的相关部分:
set(CMAKE_CXX_COMPILER /usr/bin/g++)
project(monilog LANGUAGES CXX VERSION 0.0.1)
set(PYBIND11_PYTHON_VERSION 3.8)
find_package(pybind11 REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
add_library(mylib SHARED MyLib.cc MyLib.h)
set_property(TARGET mylib PROPERTY CXX_STANDARD 17)
target_link_libraries(mylib ${PYTHON_LIBRARIES})
set_target_properties(mylib PROPERTIES VERSION ${PROJECT_VERSION})
set_target_properties(mylib PROPERTIES SOVERSION 1)
set_target_properties(mylib PROPERTIES PUBLIC_HEADER MyLib.h)
Run Code Online (Sandbox Code Playgroud)
知道我可能做错了什么吗?
编辑:最小工作示例
这是我的问题的一个最小示例,包含以下文件:
example.h#include <pybind11/stl.h>
namespace Example
{
void simple_func(std::string …Run Code Online (Sandbox Code Playgroud) 我正在开发一个带有 C++ 扩展模块的 python 包,该模块通过 pybind11 与 python 代码进行互操作,并且我正在使用 CMake 构建该包(基于此答案)。
我已将软件包安装为可编辑,以帮助开发pip install -e .
我经常更新 C++ 扩展模块,每次这样做时,让我的更改生效的唯一方法是完全清理每个构建文件,卸载,然后重新安装包,这在很大程度上违背了拥有一个包的目的。用于开发目的的可编辑安装。
有没有一种方法可以使用扩展模块进行可编辑安装,以便我可以在对其进行更改时重建模块,而无需每次都清理并重新安装整个包?
我维护一个大型 C++ 库,我使用 pybind11 部分接触了 python。C++ 库包含单元测试,我有时会在各种清理程序下运行这些测试:asan、tsan 等。这些测试运行干净,但当然测试并不完美,您无法 100% 测试所有边缘情况。
当我使用具有特定设置、特定数据集和各种选项的库时,有一个特定的 jupyter 笔记本会崩溃,这些选项可以在纯 C++ 环境中复制,但这种复制将非常耗费人力、时间并且容易出错。
如果我面前有纯 C++,我会通过 ubsan、asan 等运行笔记本,以确保我没有看到未定义的行为或段错误。有没有办法可以将这些消毒剂(或类似的东西)应用到我的笔记本上,而无需用原始 C++ 重写所有 python 胶水?