标签: pybind11

使用 C++ 扩展制作跨平台 PyPI 包(用 pybind11 包装,用 bazel 构建)

我有一个混合 C++/Python 项目。它使用pybind11包装 Python 的 C++ 代码,并使用 bazel来构建解决方案。我对这个技术栈非常满意。安装 C++ 编译器、Python 发行版和 bazel 后,bazel run命令即可下载依赖项、构建并运行整个 C++/absl/Python/numpy 集团。

但为了让用户的事情变得更简单,我想将我的代码打包为 PyPI 包,以便可以使用pip install. 我希望该包是跨平台的,可以在 Windows、Linux 和 MacOS 上运行。

在生成新版本时,建立构建、打包并将所有内容上传到 PyPI 的管道的最清晰方法是什么?

pip pypi bazel pybind11

5
推荐指数
1
解决办法
623
查看次数

pybind11:枚举与枚举类?

我理解 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 enums pybind11

5
推荐指数
1
解决办法
4540
查看次数

使用 pybind11 在 C++ 之间传递 Python 大整数(&gt;256 位)

我正在为基于 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)

c++ python bignum pybind11

5
推荐指数
1
解决办法
615
查看次数

pybind11implicitly_convertible 不起作用

我正在努力使最简单的示例发挥作用。这是我的代码:

// 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)

implicit-conversion pybind11

5
推荐指数
1
解决办法
916
查看次数

.so 似乎由于 pybind11 参数而未导出 C++ 函数

我目前正在尝试定义一个共享库,我的目标是从 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++ cmake shared-libraries pybind11

5
推荐指数
1
解决办法
137
查看次数

Python/pip:如何使用扩展模块进行可编辑包安装?

我正在开发一个带有 C++ 扩展模块的 python 包,该模块通过 pybind11 与 python 代码进行互操作,并且我正在使用 CMake 构建该包(基于答案)。

我已将软件包安装为可编辑,以帮助开发pip install -e .

我经常更新 C++ 扩展模块,每次这样做时,让我的更改生效的唯一方法是完全清理每个构建文件,卸载,然后重新安装包,这在很大程度上违背了拥有一个包的目的。用于开发目的的可编辑安装。

有没有一种方法可以使用扩展模块进行可编辑安装,以便我可以在对其进行更改时重建模块,而无需每次都清理并重新安装整个包?

python pip cmake extension-modules pybind11

5
推荐指数
0
解决办法
244
查看次数

在包含 pybind11 包装的 C++ 的 python 代码上运行 santizer(ubsan、asan 等)

我维护一个大型 C++ 库,我使用 pybind11 部分接触了 python。C++ 库包含单元测试,我有时会在各种清理程序下运行这些测试:asan、tsan 等。这些测试运行干净,但当然测试并不完美,您无法 100% 测试所有边缘情况。

当我使用具有特定设置、特定数据集和各种选项的库时,有一个特定的 jupyter 笔记本会崩溃,这些选项可以在纯 C++ 环境中复制,但这种复制将非常耗费人力、时间并且容易出错。

如果我面前有纯 C++,我会通过 ubsan、asan 等运行笔记本,以确保我没有看到未定义的行为或段错误。有没有办法可以将这些消毒剂(或类似的东西)应用到我的笔记本上,而无需用原始 C++ 重写所有 python 胶水?

c++ python address-sanitizer ubsan pybind11

5
推荐指数
0
解决办法
472
查看次数

安装python扩展模块:了解skbuild+setuptools

我是(相当大的)C++ 模拟工具的开发人员之一。免责声明:我更像是一名物理学家而不是开发人员。我使用 . 为该项目编写了 Python 绑定pybind11

我设法让 Python 模块可以用cmake. 然后我设法使用它编写了一个setup.py文件skbuild来编译Python模块:

python3 setup.py sdist bdist_wheel
Run Code Online (Sandbox Code Playgroud)

_skbuild/linux-x86_64-3.9/cmake-build/lib/(和 tar 存档中dist/cytosim-0.0.0.tar.gz)确实有一个已编译的库:cytosim.cpython-39-x86_64-linux-gnu.so

但是,当我想安装该模块时:

pip3 install dist
Run Code Online (Sandbox Code Playgroud)

我收到错误:

gcc: error: src/py3/dist.c: No such file or directory
Run Code Online (Sandbox Code Playgroud)

我很困惑,因为我没有名为py3in 的目录src

有什么指针吗?我做错了什么吗?谢谢 !

c++ python setuptools pybind11 scikit-build

5
推荐指数
1
解决办法
251
查看次数

如何支持 Pybind11 创建的 Python 枚举的 len() 方法

假设我有一个像这样的 C++ 枚举:

enum class Kind {Kind1 = 1, Kind2, Kind3};
Run Code Online (Sandbox Code Playgroud)

要使用 Pybind11 将此枚举绑定到 Python 枚举中,我正在执行以下操作:

py::enum_<Kind>(py_module, "Kind")
   .value("Kind1", Kind::Kind1)
   .value("Kind2", Kind::Kind2)
   .value("Kind3", Kind::Kind3)
   .def("__len__", 
      [](Kind p) {
         return 3;
      });
Run Code Online (Sandbox Code Playgroud)

编译代码后,如果我询问枚举的长度,我将收到此错误:

>>> len(Kind)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'pybind11_type' has no len()
Run Code Online (Sandbox Code Playgroud)

我有什么想法可以解决它吗?

编辑1:我在 Visual Studio 2019 (C++17) 上使用 Pybind11 版本 2.10.1。

编辑 2:我希望具有与 Python 枚举中相同的行为:

>>> from enum import Enum
>>> class Kind(Enum):
...    kind1 = …
Run Code Online (Sandbox Code Playgroud)

c++ enums pybind11

5
推荐指数
1
解决办法
320
查看次数

使用pybind11,如何将我的代码拆分为多个模块/文件?

使用pybind11,如何将我的代码拆分为多个模块/文件?这样可以加快编译步骤。Pybind11文档介绍了扩展在其他扩展模块(在此处)中声明的类型的特殊情况。但不是更通用/更简单的一种。

c++ python pybind11

4
推荐指数
1
解决办法
628
查看次数