ImportError:动态模块未定义初始化函数(initfizzbuzz)
我尝试编译 fizzbuzz.c
,目的是为了在 Python 中导入它。为了构建 fizzbuzz.c
,我使用了 python setup.py build_ext -i
这个命令。
构建完成后,我尝试导入 fizzbuzz.c
,但是出现了下面的错误。请问我该如何解决这个问题呢?
错误
>>> 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],
)
6 个回答
你需要定义一个叫做 init_fizzbuzz
的函数,这个函数的作用是初始化这个模块。这个函数还应该调用 Py_InitModule
,来设置 Python 中 C 函数的绑定。想了解更多信息,可以查看 这个教程。
在你的情况下,你的代码应该调整成类似下面这样的形式:
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);
}
用下面的方式来运行你的 Python 脚本:
do python3 ./yourpythonscript
而不是这样:
python ./yourpythonscript
即使你把 python 设置成了 python3 的别名也不行。
你在编译 boost 和 boost-python 时,名字必须完全一致:
brew reinstall boost --with-python3 --without-python
brew reinstall boost-python --with-python3 --without-python
值得注意的是,如果库是为不同的Python版本编译的,也可能会出现相同的错误。举个例子,如果共享对象是为Python 3编译的,但你却试图从Python 2中导入这个模块,就会出问题。
这个错误也会发生在使用 boost::python 的时候,如果模块的名字和编译出来的 .so 文件的名字不一样。例如:
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);
}
编译命令:
g++ -fpic -shared -o libfoo.so -Wl,-soname,"libfoo.so" hello.cpp -I<path/to/python> -L/usr/local/lib -lboost_python-py34
当在 python 中用 import libfoo
导入时,会出现以下错误:
ImportError: dynamic module does not define init function (PyInit_libfoo)
这是因为 "libhello" 和 "libfoo" 这两个名字不匹配。
Python不支持随便的C文件作为模块。你需要遵循一些特定的规则,让Python知道你的模块支持哪些功能。
为了做到这一点,Python会寻找一个叫做init<name>
的函数,其中<name>
就是模块的名字。比如,Python在找initfizzbuzz
,但没找到,所以加载模块失败了。
除了这个初始化函数,你还需要提供一个结构,说明有哪些可用的函数,并且你的函数需要能够处理Python的数据类型作为参数。Python提供了一些实用的函数和定义,让这件事变得相对简单。
我强烈建议你查看一下扩展和嵌入Python解释器的教程。这个教程会教你如何让你的fizzbuzz
C代码作为Python模块正常工作。