J'ai essayé de compiler fizzbuzz.c
à importer depuis python. Pour construire fizzbuzz.c
,J'ai utilisé python setup.py build_ext -i
.
Après l'avoir construit, j'ai essayé d'importer fizzbuzz.c
mais l'erreur ci-dessous s'est produite. Comment puis-je résoudre ce problème ?
>>> import fizzbuzz
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: dynamic module does not define init function (initfizzbuzz)
#include <stdio.h>
void fizzbuzz(int n){
for (int i=1; i <= n; i++){
if (i % 3 == 0 && i % 5 ==0){
printf("fizzbuzz %d \n", i);
}
else if (i % 3 == 0){
printf("fizz %d \n", i);
}
else if(i % 5 == 0){
printf("buzz %d \n", i);
}
}
}
from distutils.core import setup, Extension
module = Extension('fizzbuzz', ['fizzbuzz.c'])
setup(
name='fizzbuzz',
version='1.0',
ext_modules=[module],
)
Python ne supporte pas et ne peut pas supporter les fichiers C arbitraires en tant que modules. Vous devrez suivre certaines conventions pour que Python connaisse les fonctions prises en charge par votre module.
Pour ce faire, Python recherchera un init<name>
fonction, où <name>
est le nom du module. Python était à la recherche de initfizzbuzz
mais ne l'a pas trouvée. Le chargement du module a donc échoué.
Outre un initialiseur, vous devez également fournir une structure détaillant les fonctions disponibles. Votre fonction devra également gérer Python utilise comme arguments. Python fournit vous avec les fonctions utilitaires nécessaires et définit pour rendre cela assez facile.
Je vous recommande vivement de suivre le Extension et intégration du Python . Il vous apprend tout ce que vous devez savoir pour que votre code fizzbuzz
C fonctionne en tant que Python.
L'erreur se produit également lors de l'utilisation de boost :: python si le nom du module est différent du nom du fichier .so compilé. Par exemple:
hello.cpp
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
using namespace std;
using namespace boost::python;
int helloWorld(){
cout << "Hello world!" << endl;
return 0;
}
BOOST_PYTHON_MODULE(libhello) {
def("hello_world", helloWorld);
}
commande de compilation:
g++ -fpic -shared -o libfoo.so -Wl,-soname,"libfoo.so" hello.cpp -I<path/to/python> -L/usr/local/lib -lboost_python-py34
Lorsque vous incluez in python avec import libfoo
l'erreur suivante se produit:
ImportError: dynamic module does not define init function (PyInit_libfoo)
C'est parce que "libhello" et "libfoo" ne correspondent pas.
Notification valable - la même erreur peut se produire si la bibliothèque est compilée pour une autre python. Par exemple, si l'objet partagé est pour python 3, mais vous essayez d'importer module de python 2.
Vous devez définir une fonction nommée init_fizzbuzz
, qui devrait contenir le code pour initialiser le module. Cette fonction devrait aussi appeler Py_InitModule
, pour configurer les liaisons pour les fonctions c en Python. Pour plus d'informations, consultez ce tutoriel .
Dans votre cas, votre code devrait être adapté à quelque chose comme ceci:
static PyObject* py_fizzbuzz(PyObject* self, PyObject* args)
{
int value;
if (!PyArg_ParseTuple(args, "i", &value))
return NULL;
for (int i=1; i <= n; i++){
if (i % 3 == 0 && i % 5 ==0){
printf("fizzbuzz %d \n", i);
}
else if (i % 3 == 0){
printf("fizz %d \n", i);
}
else if(i % 5 == 0){
printf("buzz %d \n", i);
}
}
// Return value.
return Py_BuildValue("i", 0);
}
// Mapping between python and c function names.
static PyMethodDef fizzbuzzModule_methods[] = {
{"fizzbuzz", py_fizzbuzz, METH_VARARGS},
{NULL, NULL}
};
// Module initialisation routine.
void init_fizzbuzz(void)
{
// Init module.
(void) Py_InitModule("fizzbuzz", fizzbuzzModule_methods);
}
faire python3 ./votrepythonscript
au lieu de
python ./votrepythonscript
même si vous avez python aliasé comme python3
Le nom doit être exact avec lequel vous compilez boost et boost-python: brassez réinstallez boost --with-python3 --without-python brassez réinstallez boost-python --with-python3 --without-python
Si vous utilisez python 3, vous devez appliquer les modifications suivantes à votre code,
static struct PyModuleDef fizzbuzzModuleDef =
{
PyModuleDef_HEAD_INIT,
"fizzbuzz", /* 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. */
fizzbuzzModule_methods
};
PyMODINIT_FUNC PyInit_exmod(void) {
return PyModule_Create(&fizzbuzzModuleDef);
}