【问题标题】:Extending python with non python aware C library?使用不支持 python 的 C 库扩展 python?
【发布时间】:2021-02-18 09:24:06
【问题描述】:

我想创建一个使用不支持 python 的 C 库和 ctypes 的模块。

根据this documentation关于创建python的C扩展,我需要提供一个带有签名PyObject* PyInit_modulename(void)的模块初始化函数。与使用我已经拥有的 ctypes 的包装器相比,这看起来很复杂。

到目前为止,我在 unix 上测试了使用 setpuptools 构建扩展,并且它有效。它既简单又方便。但它在 Windows 上不起作用。我使用cibuildwheel 和 github 操作为包括 Windows 在内的所有操作系统构建轮子。 Windows上编译失败,因为找不到函数PyInit_ext

因此,我需要将我的代码编译为纯 DLL(Windows 共享库)。然后我可以使用ctypes 加载库。这可以通过cibuildwheel 使用的setuptools 来完成吗?

我该怎么做?

这是我的setup.cfg 文件:

[metadata]
name = hello_chmike
version = 0.0.0
url = https://github.com/chmike/hello
maintainer = Christophe Meessen
maintainer_email = christophe@meessen.net
description = Simple python module with external C library
long_description = file: README.md
long_description_content_type = text/markdown
keywords = Example
license = BSD 3-Clause License
license_file = LICENSE.txt
classifiers =
    License :: OSI Approved :: BSD License
    Programming Language :: Python :: 3
    Operating System :: OS Independent
    Topic :: Utilities

[options]
packages = hello
python_requires = >=3.6

这是我目前拥有的setup.py 文件,但它使用扩展名并不好:

from setuptools import setup, Extension

setup(
  ext_modules=[Extension('hello.ext',
                       ['src/hello.c'],
                       depends=['src/hello.h'],
                       include_dirs=['src'],
              )],
)

文件hello.c的内容如下:

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS 1
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// hello return a heap allocated string containing the name appended 
// to "hello " and followed by "!".
char *hello(char *name) {
    char *buf = malloc(7+strlen(name));
    sprintf(buf, "hello %s!", name);
    return buf;
}

【问题讨论】:

  • 如果你不需要在那个函数中做任何事情,只提供一个空函数?我不太了解这件事,但您似乎没有提供。
  • @user202729 确实如此。我没有提供一个。如果我提供一个虚拟的必需功能,它会起作用吗?那个接缝就像一个黑客,但可以解决我的问题。我会试试的。
  • (另一方面,为什么它甚至可以在 UNIX 上编译?)
  • @user202729 根据另一个论坛上的this answer,这是因为在 unix 和 macOS 上,符号是隐式导出的。因此没有编译错误。在 Windows 上,必须显式导出符号,并在编译时检测到丢失的符号。我可以将该符号定义为一个函数,它可以工作。这个函数应该有什么签名?
  • 我确实说过我不太了解这件事。阅读文档。

标签: python python-3.x python-extensions


【解决方案1】:

在不同操作系统上获取可移植代码并使用 python 构建工具和cibuildwheel 获取预编译模块的唯一可行解决方案是创建一个真正的 python 扩展。

这意味着创建一个 Python 扩展 C 代码来包装与 Python 无关的 C 库。包装意味着我们根据 Python C 扩展标准的要求创建 C 函数,这些函数从我的库中调用与 python 无关的 C 函数。

使用 ctypes 包装与 python 无关的 C 库在用于特定操作系统(如 linux)时将起作用。但是操作系统之间的执行上下文是如此不同,以至于试图制作一个适用于每个操作系统的 ctypes 包装器需要在 python 包装器中进行复杂的黑客攻击和平台切换。

通过使用真正的 Python 扩展 C 代码,我们避免了这种复杂性。我希望我一开始就知道这一点。

【讨论】:

    猜你喜欢
    • 2012-06-21
    • 1970-01-01
    • 2022-06-17
    • 2010-11-07
    • 2014-07-24
    • 1970-01-01
    • 2019-11-23
    • 2012-03-02
    • 2017-06-11
    相关资源
    最近更新 更多