Ошибка импорта модуля C ++ Python: & quot; неопределенный символ: Py_InitModule3 & quot; (Py_InitModule ())

Я только начинаю попытку написать свой первый модуль расширения Python на C и использую инструкции, предоставленные на https://www.tutorialspoint.com/python/python_further_extensions.htm

Я использую Linux Mint 18.1, использую Python 3.6.1 в его версии virtualenv.

В качестве первого шага я собрал очень минималистичную версию модуля 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");
}

и вот код файла setup.py, который я использовал для компиляции C-кода uniqueCombinations.cpython-36m-x86_64-linux-gnu.so:

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

6

Решение

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')">>>
7

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]