2017-04-25 7 views
1

Je commence tout juste une tentative d'écrire mon premier module d'extension Python en C et utilisent les instructions fournies à https://www.tutorialspoint.com/python/python_further_extensions.htmC++ Module Python erreur d'importation: "symbole non défini: Py_InitModule3" (Py_InitModule())

Je suis sur Linux Mint 18.1, en utilisant Python 3.6.1 dans sa version virtualenv.

Comme première étape, j'ai compilé une version très minimaliste du module Python que je prévois d'écrire.

Voici mon code 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"); 
} 

et ici le code du fichier setup.py je l'ai utilisé pour compiler le code 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'])]) 

À ma grande surprise la module ne se charge pas correctement à l'importation:

>>> 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 

Why am I getting this error?

And what should I do to be able to load the compiled module properly?

Ici, le protocole de construction avec un avertissement sur déclaration implicite de 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 
+0

À partir de ce commentaire: vue 868 fois, aucune Votes. que diable? – Scott

Répondre

2

Le Py_InitModule (Py_InitModule3) n'est plus utilisé. Il est nécessaire de créer une structure PyModuleDef à la place, puis de lui transmettre une référence à PyModule_Create.

Ci-dessous le code C-à partir duquel le module créé ne jette pas une erreur lors de l'importation:

#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); 
} 

Voici le protocole de construction:

$ 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 

et la session de la console Python interactif avec l'importation réussie :

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