python - ImportError: el módulo dinámico no define la función init(initfizzbuzz)
cython (6)
Debe definir una función llamada init_fizzbuzz
, que debe contener el código para inicializar el módulo. Esta función también debe llamar a Py_InitModule
, para configurar los enlaces para las funciones c en Python. Para obtener más información, consulte este tutorial .
En su caso, su código debería adaptarse a algo como esto:
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);
}
Intenté compilar fizzbuzz.c
para importar de python. Para construir fizzbuzz.c
, utilicé python setup.py build_ext -i
.
Después de fizzbuzz.c
, traté de importar fizzbuzz.c
pero ocurrió el siguiente error. Como puedó resolver esté problema ?
Error
>>> import fizzbuzz
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: dynamic module does not define init function (initfizzbuzz)
fizzbuzz.c
#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);
}
}
}
setup.py
from distutils.core import setup, Extension
module = Extension(''fizzbuzz'', [''fizzbuzz.c''])
setup(
name=''fizzbuzz'',
version=''1.0'',
ext_modules=[module],
)
El error también ocurre cuando se usa boost::python , si el nombre del módulo es diferente al nombre de archivo .so compilado. Por ejemplo:
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);
}
comando de compilación:
g++ -fpic -shared -o libfoo.so -Wl,-soname,"libfoo.so" hello.cpp -I<path/to/python> -L/usr/local/lib -lboost_python-py34
Al incluir en python con import libfoo
se produce el siguiente error:
ImportError: dynamic module does not define init function (PyInit_libfoo)
Esto se debe a que "libhello" y "libfoo" no coinciden.
Python no admite y no puede admitir archivos C arbitrarios como módulos. Deberá seguir ciertas convenciones para que Python sepa qué funciones admite su módulo.
Para hacerlo, Python buscará una función init<name>
, donde <name>
es el nombre del módulo. Python estaba buscando initfizzbuzz
pero no lo encontró, por lo que se produjo un initfizzbuzz
al cargar el módulo.
Además de un inicializador, también debe proporcionar una estructura que detalle qué funciones están disponibles, y su función necesitará manejar los tipos de Python como argumentos. Python le proporciona las funciones de utilidad necesarias y las define para que sea lo suficientemente fácil.
Le recomiendo encarecidamente que siga el tutorial Extender e incrustar el intérprete de Python . Te enseña todo lo que necesitas saber para que tu código fizzbuzz
C funcione como un módulo de Python.
Si usa Python 3, entonces necesita tener los siguientes cambios en su código,
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);
}
Vale la pena notificar: el mismo error puede ocurrir si la biblioteca se compila para diferentes versiones de Python. Por ejemplo, si el objeto compartido es para python 3, pero intenta importar el módulo de python 2.
hacer python3 ./yourpythonscript
en lugar de
python ./yourpythonscript
incluso si tiene un alias de Python como python3
El nombre debe ser exacto con el que compile boost y boost-python: brew reinstall boost --with-python3 --without-python brew reinstalar boost-python --with-python3 --without-python