编译器找不到Py_InitModule()..它已经被弃用了吗?如果是的话,我应该使用什么?

28

我试图为Python编写一个C扩展。使用以下代码时,我收到编译器警告:

implicit declaration of function ‘Py_InitModule’

运行时出现以下错误:

undefined symbol: Py_InitModule

我已经花费了数小时的时间进行搜索,但没有找到解决方案。我尝试了多种语法的微小更改,甚至发现一篇帖子表明该方法已被弃用。然而,我没有找到替代方法。

这是代码:

#include <Python.h>

//a func to calc fib numbers
int cFib(int n)
{
    if (n<2) return n;
    return cFib(n-1) + cFib(n-2);
}


static PyObject* fib(PyObject* self,PyObject* args)
{
    int n;
    if (!PyArg_ParseTuple(args,"i",&n)) 
        return NULL;    
    return Py_BuildValue("i",cFib(n));
}

static PyMethodDef module_methods[] = {
    {"fib",(PyCFunction) fib, METH_VARARGS,"calculates the fibonachi number"},
    {NULL,NULL,0,NULL}
};

PyMODINIT_FUNC initcModPyDem(void)
{
    Py_InitModule("cModPyDem",module_methods,"a module");
}

如果有帮助的话,这是我的setup.py文件:

from distutils.core import setup, Extension

module = Extension('cModPyDem', sources=['cModPyDem.c'])
setup(name = 'packagename', 
    version='1.0',
    description = 'a test package',
    ext_modules = [module])

并且test.py中的测试代码:

import cModPyDem

if __name__ == '__main__' :

    print(cModPyDem.fib(200))
任何帮助都将不胜感激。

你正在编译哪个版本的Python? - MattDMo
抱歉,是的,我正在使用Python3进行编译。 - Sam Redway
2个回答

44
你所使用的代码在 Python 2.x 中可以正常工作,但在 Python 3.x 中已不再使用Py_InitModule。现在,您需要创建一个PyModuleDef结构,并将其引用传递给PyModule_Create
该结构应如下所示:
static struct PyModuleDef cModPyDem =
{
    PyModuleDef_HEAD_INIT,
    "cModPyDem", /* name of module */
    "",          /* module documentation, may be NULL */
    -1,          /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
    module_methods
};

然后你的PyMODINIT_FUNC函数会像这样:

PyMODINIT_FUNC PyInit_cModPyDem(void)
{
    return PyModule_Create(&cModPyDem);
}

请注意,PyMODINIT_FUNC 函数的名称必须采用 PyInit_<name> 的形式,其中 <name> 是您的模块名称。
我认为如果您阅读Python 3.x文档中的Extending,这将是值得的。它详细描述了如何在现代Python中构建扩展模块。

非常好 - 你提供的代码可以直接使用,只需要进行一些小的修改 - PyMODINIT_FUNC PyInit_cModPyDem(void){} - 是正确的方式。谢谢,是值得查阅文档的。 - Sam Redway
return PyModule_Create(&ModPyDem);中,正确的应该是return PyModule_Create(&cModPyDem);吗? - macabeus
顺便提一下,在Python 3.6.8 Ubuntu 18.04中会出现“警告:缺少‘struct PyModuleDef’的字段‘m_slots’的初始化程序”的情况。 - Ciro Santilli OurBigBook.com

3
我遇到了与Py_InitModule()相同的问题。我开始阅读Python 3文档,特别是“扩展和嵌入Python解释器”文档。但该文档中名为“一个简单的例子”的章节省略了细节。因此,我在谷歌上搜索了这个scipy讲座:http://www.scipy-lectures.org/advanced/interfacing_with_c/interfacing_with_c.html,它在很多方面更适合新手学习Python-C API扩展...但它没有更新到Python v3。因此,请参考scipy讲座、Python 3文档以及这个StackOverflow讨论,从中提取出你需要的相关信息。

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