【问题标题】:C++ Python module import error: "undefined symbol: Py_InitModule3" ( Py_InitModule () )C++ Python 模块导入错误:“未定义符号:Py_InitModule3”(Py_InitModule ())
【发布时间】:2017-09-23 03:12:23
【问题描述】:

我刚刚开始尝试用 C 语言编写我的第一个 Python 扩展模块,并且正在使用 https://www.tutorialspoint.com/python/python_further_extensions.htm 提供的说明

我在 Linux Mint 18.1 上,在其 virtualenv 版本中使用 Python 3.6.1。

作为第一步,我已经编译了我计划编写的 Python 模块的一个非常简约的版本。

这里是我的 C 代码:

include <Python.h>

static PyObject* uniqueCombinations(PyObject* self)
{
    return Py_BuildValue("s", "uniqueCombinations() return value (is of type 'string')");
}

static char uniqueCombinations_docs[] =
    "usage: uniqueCombinations(lstSortableItems, comboSize)\n";

static PyMethodDef uniqueCombinations_funcs[] = {
    {"uniqueCombinations", (PyCFunction)uniqueCombinations, 
     METH_NOARGS, uniqueCombinations_docs},
    {NULL}
};

void inituniqueCombinations(void)
{
    Py_InitModule3("uniqueCombinations", uniqueCombinations_funcs,
                   "Extension module uniqueCombinations v. 0.01");
}

这里是我用来将 C 代码编译为 uniqueCombinations.cpython-36m-x86_64-linux-gnu.so 的 setup.py 文件的代码:

from distutils.core import setup, Extension

setup(name='uniqueCombinations', version='0.01',  \
      ext_modules=[Extension('uniqueCombinations', ['uniqueCombinations_pythonCmodule_v-0.01_Cg.c'])])

令我惊讶的是,模块在导入时没有正确加载:

>>> import uniqueCombinations
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: uniqueCombinations.cpython-36m-x86_64-linux-gnu.so: undefined symbol: Py_InitModule3

为什么会出现此错误?

我应该怎么做才能正确加载编译的模块?

这里的构建协议带有关于 Py_InitModule3 隐式声明的警告:

$ python uniqueCombinations_pythonCmodule_v-0.01_setup.py_Cg.py build
running build
running build_ext
building 'uniqueCombinations' extension
gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/usr/local/include/python3.6m -c uniqueCombinations_pythonCmodule_v-0.01_Cg.c -o build/temp.linux-x86_64-3.6/uniqueCombinations_pythonCmodule_v-0.01_Cg.o
uniqueCombinations_pythonCmodule_v-0.01_Cg.c: In function ‘inituniqueCombinations’:
uniqueCombinations_pythonCmodule_v-0.01_Cg.c:19:5: warning: implicit declaration of function ‘Py_InitModule3’ [-Wimplicit-function-declaration]
     Py_InitModule3("uniqueCombinations", uniqueCombinations_funcs,
     ^
creating build/lib.linux-x86_64-3.6
gcc -pthread -shared build/temp.linux-x86_64-3.6/uniqueCombinations_pythonCmodule_v-0.01_Cg.o -o build/lib.linux-x86_64-3.6/uniqueCombinations.cpython-36m-x86_64-linux-gnu.so

【问题讨论】:

  • 截至此评论:浏览了 868 次,没有投票。什么鬼?

标签: python c++ python-3.x python-import extension-modules


【解决方案1】:

不再使用 Py_InitModule (Py_InitModule3)。有必要改为创建一个 PyModuleDef 结构,然后将对它的引用传递给 PyModule_Create。

在导入时创建的模块不会引发错误的 C 代码下方:

#include <Python.h>

static PyObject* uniqueCombinations(PyObject* self)
{
    return Py_BuildValue("s", "uniqueCombinations() return value (is of type 'string')");
}

static char uniqueCombinations_docs[] =
    "usage: uniqueCombinations(lstSortableItems, comboSize)\n";

/* deprecated: 
static PyMethodDef uniqueCombinations_funcs[] = {
    {"uniqueCombinations", (PyCFunction)uniqueCombinations, 
     METH_NOARGS, uniqueCombinations_docs},
    {NULL}
};
use instead of the above: */

static PyMethodDef module_methods[] = {
    {"uniqueCombinations", (PyCFunction) uniqueCombinations, 
     METH_NOARGS, uniqueCombinations_docs},
    {NULL}
};


/* deprecated : 
PyMODINIT_FUNC init_uniqueCombinations(void)
{
    Py_InitModule3("uniqueCombinations", uniqueCombinations_funcs,
                   "Extension module uniqueCombinations v. 0.01");
}
*/

static struct PyModuleDef Combinations =
{
    PyModuleDef_HEAD_INIT,
    "Combinations", /* name of module */
    "usage: Combinations.uniqueCombinations(lstSortableItems, comboSize)\n", /* 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 PyInit_Combinations(void)
{
    return PyModule_Create(&Combinations);
}

这里是构建协议:

$ python uniqueCombinations_pythonCmodule_v-0.01_setup.py_Cg.py build
running build
running build_ext
building 'Combinations' extension
gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/usr/local/include/python3.6m -c uniqueCombinations_pythonCmodule_v-0.01_Cg.c -o build/temp.linux-x86_64-3.6/uniqueCombinations_pythonCmodule_v-0.01_Cg.o
gcc -pthread -shared build/temp.linux-x86_64-3.6/uniqueCombinations_pythonCmodule_v-0.01_Cg.o -o build/lib.linux-x86_64-3.6/Combinations.cpython-36m-x86_64-linux-gnu.so

以及成功导入的交互式 Python 控制台会话:

>>> import Combinations
>>> dir(Combinations)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'uniqueCombinations']
>>> Combinations.__doc__
'usage: Combinations.uniqueCombinations(lstSortableItems, comboSize)\n'
>>> Combinations.uniqueCombinations()
"uniqueCombinations() return value (is of type 'string')"
>>> 

【讨论】:

  • 有关于 Py_InitModule 的迁移说明吗?
  • @benjimin :对不起,我已经很长时间不再关注这个主题了。还有其他人知道上述问题的答案吗?附言将您的评论变成一个问题以吸引更广泛的受众是很有意义的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-23
  • 2012-10-13
  • 2016-02-03
  • 2020-07-13
  • 1970-01-01
  • 2021-11-16
  • 2021-05-20
相关资源
最近更新 更多