问题
I tried to compile fizzbuzz.c
to import from python. For building fizzbuzz.c
,I used python setup.py build_ext -i
.
After building it, I tried to import fizzbuzz.c
but the error below occurred.
How can I solve this problem ?
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],
)
回答1:
Python doesn't and cannot support arbitrary C files as modules. You'll have to follow certain conventions to let Python know what functions your module supports.
To do so, Python will look for a init<name>
function, where <name>
is the module name. Python was looking for initfizzbuzz
but failed to find it, so loading the module failed.
Apart from an initialiser, you also need to provide a structure detailing what functions are available, and your function will need to handle Python types as arguments. Python provides you with the necessary utility functions and defines to make that easy enough.
I strongly urge you follow the Extending and Embedding the Python Interpreter tutorial. It teaches you everything you need to know to make your fizzbuzz
C code work as a Python module.
回答2:
The error also occurs, when using boost::python, if the module name is different to the compiled .so file name. For example:
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);
}
compilation command:
g++ -fpic -shared -o libfoo.so -Wl,-soname,"libfoo.so" hello.cpp -I<path/to/python> -L/usr/local/lib -lboost_python-py34
When including in python with import libfoo
the following error occurs:
ImportError: dynamic module does not define init function (PyInit_libfoo)
This is because of "libhello" and "libfoo" do not match.
回答3:
Worth notify - same error can occur if library is compiled for different python version. For example, if shared object is for python 3, but you try to import module from python 2.
回答4:
You should define a function named init_fizzbuzz
, that should contain the code to initialize the module. This function should also call Py_InitModule
, to setup the bindings for the c functions in Python. For further info, check out this tutorial.
In yor case, your code should be adapted to something like this:
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);
}
回答5:
do python3 ./yourpythonscript
instead of
python ./yourpythonscript
even if you have python aliased as python3
The name must be exact with which you compile boost and boost-python: brew reinstall boost --with-python3 --without-python brew reinstall boost-python --with-python3 --without-python
回答6:
If you use python 3 then you need to have the following changes on your 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);
}
来源:https://stackoverflow.com/questions/24226001/importerror-dynamic-module-does-not-define-init-function-initfizzbuzz