如何构建Python C扩展,以便我可以从一个模块中导入它。

23

我有一个用 distutils 打包的 Python 项目,其中有许多子模块。我希望在其中一些子模块中使用 C 构建一些 Python 扩展,但我不知道如何使 Python 扩展位于子模块中。以下是我正在寻找的最简单示例:

这是我的 Python 扩展 c_extension.c

#include <Python.h>

static PyObject *
get_answer(PyObject *self, PyObject *args)
{
    return Py_BuildValue("i", 42);
}

static PyMethodDef Methods[] = {
    {"get_answer",  get_answer, METH_VARARGS, "The meaning of life."},
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
initc_extension(void) {
  (void) Py_InitModule("c_extension", Methods);
}

以下是一个可用的 setup.py 文件示例:

from distutils.core import setup
from distutils.extension import Extension

setup(name='c_extension_demo',
      ext_modules = [Extension('c_extension', sources = ['c_extension.c'])])

在虚拟环境中安装后,我可以执行以下操作:

>>> import c_extension
>>> c_extension.get_answer()
42

但是我想让c_extension存在于一个子模块中,比如说foo.bar。为了达到在Python shell中获得这样的行为,我需要在这个过程中进行哪些改变?

>>> import foo.bar.c_extension
>>> foo.bar.c_extension.get_answer()
42

相关链接:https://dev59.com/aGct5IYBdhLWcg3wa87p - Brad Solomon
对于 python >= 3.10distutils 已被弃用,请参见我的另一个帖子了解详情。 - Ham
1个回答

17

只需更改

Extension('c_extension', ...)

为了

Extension('foo.bar.c_extension', ...)

您需要在每个foobar目录中都有一个__init__.py文件,这是通常的做法。要将这些文件与您的setup.py一起打包,请添加以下内容:
packages = ['foo', 'foo.bar'],

将以下代码添加到您的setup()调用中,并且您需要相应的目录结构:

setup.py
foo/
    __init__.py
    bar/
        __init__.py

在您的源目录中。

谢谢您的回答,但是那对我没用。我在每个目录下都添加了 __init__.py 文件,并在设置命令中添加了 foo.bar. 前缀,但在 Python shell 中出现了以下情况:>>> import foo.bar.c_extension Traceback (most recent call last): File "", line 1, in ImportError: No module named c_extension - Rich
你使用的是哪个版本的Python?我正在测试2.7.3。 - nneonneo
5
不要从你的源代码目录中进行测试。这将尝试从源代码目录中的foo/bar导入,而该目录中没有c_extension。 - nneonneo
哦,没错。就是这样。谢谢你的帮助! - Rich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接