通过 cmake 从 C++ 扩展构建 Python 子模块

2024-01-23

我正在尝试通过 cmake 将 c++ 扩展作为子模块合并到现有的 python 库中。构建 C++ 扩展可以正常工作,并将其作为 python 模块导入也可以,但不能作为头库的子模块。

我有以下目录结构:

frontend/
   foo.py
   bar.py
   backend/
      backend.cpp

该扩展通过 pybind 绑定到 python 模块:

PYBIND11_MODULE(backend, m)
{
    m.doc() = "backend c++ implementation"; // optional module docstring
    m.def("method", &method, "The method I want to call from python.");
}

在 CMakeLists.txt 中,相关行是:

pybind11_add_module(backend "frontend/backend/backend.cpp")

我已按照说明表进行操作here https://stackoverflow.com/questions/42048421/how-to-package-a-python-c-extension-such-that-it-is-a-submodule-of-a-normal-pyth and here https://stackoverflow.com/questions/42585210/extending-setuptools-extension-to-use-cmake-in-setup-py编写 setup.py 脚本。我想最重要的几行看起来像这样:

from setuptools import setup, Extension, find_packages
from setuptools.command.build_ext import build_ext
from setuptools.command.test import test as TestCommand

class CMakeExtension(Extension):
    def __init__(self, name, sourcedir=".", sources=[]):
        Extension.__init__(self, name, sources=[])


class CMakeBuild(build_ext):
    def run(self):
        build_directory = os.path.abspath(self.build_temp)
        if not os.path.exists(self.build_temp):
            os.makedirs(self.build_temp)

        cmake_list_dir = os.path.abspath(os.path.dirname(__file__))
        print("-" * 10, "Running CMake prepare", "-" * 40)
        subprocess.check_call(
            ["cmake", cmake_list_dir], cwd=self.build_temp,
        )

        print("-" * 10, "Building extensions", "-" * 40)
        cmake_cmd = ["cmake", "--build", "."] + self.build_args
        subprocess.check_call(cmake_cmd, cwd=self.build_temp)

        # Move from build temp to final position
        for ext in self.extensions:
            self.move_output(ext)

    def move_output(self, ext):
        build_temp = Path(self.build_temp).resolve()
        dest_path = Path(self.get_ext_fullpath(ext.name)).resolve()
        source_path = build_temp / self.get_ext_filename(ext.name)
        dest_directory = dest_path.parents[0]
        dest_directory.mkdir(parents=True, exist_ok=True)
        self.copy_file(source_path, dest_path)


extensions = [CMakeExtension("backend")]

setup(
    name="frontend",
    packages=["frontend"],
    ext_modules=extensions,
    cmdclass=dict(build_ext=CMakeBuild),
)

但这并不使backend的子模块frontend,而是一个独立的模块。所以这有效:

from backend import method

但为了避免与其他库的命名问题,我想要的是:

from frontend.backend import method

将 pybinding 或扩展调用中的命名更改为extensions = [CMakeExtension("frontend.backend")]不幸的是没有解决我的问题,安装程序没有找到backend.<platform>.so那么共享库,因为它寻找frontend/backend.<platform>.so,它不存在。我该如何解决这个问题?


我想我已经通过以下几行解决了这个问题:

更改setup.py文件:

ext_modules = [
    Extension(
        "frontend.backend", sources=["frontend/backend/backend.cpp"]
    )
]

CMakeLists.txt 文件中的更改:

pybind11_add_module(backend "frontend/backend/backend.cpp")
set_target_properties( backend
    PROPERTIES
    ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/frontend"
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/frontend"
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/frontend"
)

共享库对象 backend.platform.so 必须位于 frontend 目录中。 pybind 模块名称和源文件 .cpp 都不应包含任何“.”在名字中,因为get_ext_fullpath()方法来自build_ext将被点分割。只有前端目录包含init.py 文件。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过 cmake 从 C++ 扩展构建 Python 子模块 的相关文章

随机推荐

  • Solr 在单词拼写不正确时将其识别为拼写正确

    我正在跟随 Solr拼写检查组件文档 http wiki apache org solr SpellCheckComponent 但似乎无法让它发挥作用 拼写检查组件似乎正在运行 但 Solr 会在单词未运行时将其识别为拼写正确 我怎样才能
  • Javascript函数有子函数/变量

    这是工作代码 var test function console log test data test data hello test set function data test data data test set Test test
  • 如何在PHP中使用箭头函数?

    我开始了解PHP 7 4 中的箭头函数 https github com php php src pull 3941 我尝试像这样使用它们
  • 铸造明确布局的结构

    假设我有这个结构 StructLayout LayoutKind Explicit public struct Chapter4Time FieldOffset 0 public UInt16 Unused FieldOffset 2 pu
  • 主题分布:在python中进行LDA后如何查看哪个文档属于哪个主题

    我能够运行 gensim 中的 LDA 代码 并获得前 10 个主题及其各自的关键字 现在 我想进一步了解 LDA 算法的准确性 方法是查看它们将哪些文档聚类到每个主题中 这在 gensim LDA 中可能吗 基本上我想做这样的事情 但是在
  • 有没有办法仅使用 CSS 将元素的索引(子编号)作为文本插入到元素中?

    我的目标是逐行打印文本文件并在开头附加行号 就像这样 div div class line 1 asdf div div class line 2 asdfasdf div div class line 3 asdfasdfasdfasdf
  • 是否可以在 C 语言中添加类型推断?

    比方说 我们创建了 C 的重新实现 唯一的区别是 类型是推断出来的 存储类和修饰符仍然需要 给定 const static restrict 等 让我们将注意力限制在单个 暂时归档 C 程序 能做到吗 主要有哪些 障碍 关于可能导致类型推断
  • 为什么在 V8 中使用此代码片段 <= 比 < 慢?

    我正在阅读幻灯片使用 V8 突破 Javascript 速度限制 https v8 io12 appspot com 16 并且有一个类似下面代码的示例 我不明白为什么 lt 慢于 lt 在这种情况下 有人能解释一下吗 如有任何意见 我们将
  • Google Ads 链接器命令失败,退出代码为 1(使用 -v 查看调用)

    我最近从 iAd 切换到 Google Ads 它似乎在模拟器上运行良好 但每当我尝试在 iOS 设备上运行它时 我都会收到此错误 这有什么问题吗 我的项目发生了同样的错误 以下解决方案有效 请检查您的 xcode 项目中是否启用或禁用了位
  • 谷歌地图如何在最近的道路上强制标记

    我正在做一个车辆跟踪项目 我从数据库中获取坐标 并显示在谷歌地图上 这是我的代码 function get coordinates checkbox var v id checkbox id if checkbox checked var
  • 构建上下文无关语法

    如何为以下语言构建上下文无关语法 L a l b m c n d p l n m p l m n p gt 1 我首先尝试 S gt abcd aAbBcd abcCdD aAbcdD AabBcCd 进而A 其他东西 但我无法让它工作 我
  • 如何合并两个没有共同祖先的分支?

    我已经开始在项目中使用 Git 其中前两次提交只是一些初始设置 gitignore 和 gitattributes 第三次提交M2添加SVN trunk的内容 I1 I2 M2 N Z 我已将 SVN 历史记录导入名为svn where M
  • Sencha 命令上的 Cordova 和 PhoneGap 初始化失败

    我已经通过 NodeJS CLI 在 Ubuntu 13 10 上安装了 PhoneGap 并开始了本机构建过程 然而 在初始化期间 这是执行的命令和相应的输出 sencha phonegap init com foo barapp Bar
  • 使用 sed 将换行符转义 '\n' 替换为转义换行符转义 '\\n'

    我正在尝试替换字面术语 n 不是换行符 而是字面量 按字面量 n using sed 我试过这个 echo Refreshing n n n state prior sed s n n g 这 有效 但我需要它来输出文字字符 n 现在我最终
  • 在 Windows 上从命令行向 git commit -m 添加换行符

    我的公司有一项政策 即对特定项目的所有签入都必须遵循 git 提交的特定多行模板 如何最简单地从 Windows 命令行创建一条包含多行的提交消息 This is almost exactly a duplicate of Add line
  • 2个列表之间的共同元素比较

    给定两个输入列表 如何创建两个输入共有的元素列表 例如 对于输入 1 2 3 4 5 6 and 3 5 7 9 结果应该是 3 5 用于输入 this this n that and this not that that 结果应该是 th
  • XCode C++ 缺少精子()

    我正在使用 C 和 XCode 创建一个命令行应用程序来保存文件权限 但是我无法识别精子 方法 错误是 使用未声明的标识符 精子 我的包含内容和有问题的代码如下 My includes include
  • Android 4.3 上的 YouTube 嵌入式播放器

    我正在尝试将 YouTube 播放器嵌入到我的网页中 如下所示 我遇到的问题是 播放器最初加载并播放第一个视频正常 但是当调用 loadVideoById 时 播放器看起来要加载视频 视频标题文本更改 但随后卡在黑屏上而不是播放 自从我的手
  • 如何使用WinAPI隐藏控制台窗口?

    我试图隐藏控制台窗口当我的C使用这个简单的应用程序启动WinAPI code define CONSOLE NAME 6FD66E14 FF0F 4B94 B8AF AFE3D42DC399 void hide window void Se
  • 通过 cmake 从 C++ 扩展构建 Python 子模块

    我正在尝试通过 cmake 将 c 扩展作为子模块合并到现有的 python 库中 构建 C 扩展可以正常工作 并将其作为 python 模块导入也可以 但不能作为头库的子模块 我有以下目录结构 frontend foo py bar py