通过 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 子模块 的相关文章

  • Pandas 多索引数据框删除行

    我的多索引 DF 如下 tuples list zip a a b b c d c d index pd MultiIndex from tuples tuples names i1 i2 df pd DataFrame 5 6 7 8 i
  • 将迭代器取消引用到临时范围时出现非指针操作数错误

    Using auto empty line auto str return str size 0 我们做得到 auto line range with first non empty ranges view drop while range
  • 如何找到 QDockWidget 标题栏的高度?

    我正在尝试找到 a 的高度QDockWidget标题栏 以便对自定义布局进行一些智能调整大小 但标题栏不是单独的小部件 它内置于停靠小部件的私有布局中 并且没有成员可以访问它 还有其他方法可以找到它的高度吗 是的 您可以使用以下命令找到标题
  • 如何将填充轮廓投影到 3D 曲面图上

    我只是想在 3D 中绘制一个表面及其轮廓 就像this http matplotlib org examples mplot3d contourf3d demo2 html例子 这是我用来执行此操作的代码 import matplotlib
  • 在 Python 中删除表达式树及其每个子表达式树中第一个元素周围的括号

    目标是实现简化操作 删除表达式树及其每个子表达式树中第一个元素周围的括号 其中表达式作为括在各个括号中的字符串输入给出 这必须适用于任意数量的括号 例如 12 3 45 6 gt 123 45 6 删除 12 周围的括号 然后删除 45 周
  • Pytest - 如何将参数传递给 setup_class?

    我有一些代码 如下所示 我得到了too few args当我运行它时出错 我没有打电话setup class明确地 所以不确定如何向它传递任何参数 我尝试用以下方法装饰该方法 classmethod 但仍然看到相同的错误 我看到的错误是这样
  • Pandas:Drop() int64 基于值返回对象

    我需要删除其中一列低于某个值的所有行 我使用了下面的命令 但这将列作为对象返回 我需要将其保留为int64 df customer id df drop df customer id df customer id lt 9999999 in
  • 为什么这些双精度数的返回值为-1.#IND?

    I have double score cvMatchContourTrees CT1 CT2 CV CONTOUR TREES MATCH I1 0 0 cout lt
  • pyspark:将 schemaRDD 保存为 json 文件

    我正在寻找一种将数据从 Apache Spark 以 JSON 格式导出到各种其他工具的方法 我认为一定有一种非常简单的方法来做到这一点 示例 我有以下 JSON 文件 jfile json key value a1 key2 value
  • 带有 epgm 的 ZeroMQ PUB/SUB 无法接收同一主机上进程发送的消息

    我的所有进程都有两个套接字 一个 PUB 和一个 SUB 并且它们都使用相同的多播地址和端口 例如 PUB 会这样做 绑定 epgm 239 192 1 1 5555 SUB 将执行以下操作 连接 epgm 239 192 1 1 5555
  • python:Windows终端中的unicode,使用的编码?

    我在 Windows 7 终端中使用 Python 解释器 我正在尝试了解 unicode 和编码 I type gt gt gt s gt gt gt s x89 gt gt gt u u gt gt gt u u xeb 问题1 字符串
  • numpy 沿第一个轴添加

    我想通过简单地沿第一个轴执行相同的加法来添加两个具有不同维度的数组 非矢量化解决方案 x np array 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 shape 4 3 2 y np a
  • 使用 STL 迭代器而不初始化它

    我想做这样的事情 container iterator it NULL switch eSomeEnum case Container1 it vecContainer1 begin break case Container2 it vec
  • 奇怪的 MSC 8.0 错误:“ESP 的值未在函数调用中正确保存...”

    我们最近尝试将一些 Visual Studio 项目分解为库 并且在测试项目中一切似乎都编译和构建得很好 其中一个库项目作为依赖项 然而 尝试运行该应用程序给我们带来了以下令人讨厌的运行时错误消息 运行时检查失败 0 ESP 的值未在函数调
  • 如何提取Python代码文件中使用的函数?

    我想创建代码文件中使用的所有函数的列表 例如 如果我们在名为 add random py 的文件中有以下代码 import numpy as np from numpy import linalg def foo print np rand
  • 通过 boost::python 将 C++ 对象传递给 python 函数

    我想在 C 应用程序中使用嵌入 python 并调用 python 脚本中定义的函数 该函数的参数是一个 C 对象 看我的代码 class Test public void f std cout lt lt sss lt
  • C 警告函数调用中缺少标记

    这是我的警告 Missing sentinel in function call 我怎样才能删除它 我正在使用 linux 和 gcc 编译器 看来您可能没有终止数组声明NULL 如果没有 null 您可能会遇到一些内存怪异 因为运行时将不
  • 如何注销多个非当前用户的会员用户?

    我正在使用属于 MVC2 默认项目一部分的 MembershipProvider 我希望能够获取用户名列表 注销用户 并在需要时销毁他们的会话 我能想到的最接近的是 foreach string userName in UserNames
  • Django - 在启动时执行代码

    我正在使用 Django 1 9 3 我有一个包含多个应用程序的项目 我想在项目启动时更新其中一个应用程序的表 用例 例如 假设我想在我的网站上销售商品 我有一个包含模型项目的应用程序 我在 Django 之外有一个网络服务 它提供服务 g
  • Python:从 apache authnz_ldap 获取用户

    我正在通过 Apache2 的 authnz ldap 模块成功验证 ldap 用户 我不清楚如何在他们登录后获取他们的用户名 以便我可以通过任何以下表单 网页与他们交互 我尝试过典型的方法 os getenv os environ get

随机推荐

  • 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