我尝试编译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)
#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],
)
答案 0 :(得分:48)
如果模块名称与编译的.so文件名不同,则在使用boost::python时也会发生错误。例如:
<强> 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)
这是因为&#34; libhello&#34;和&#34; libfoo&#34;不符合。
答案 1 :(得分:25)
值得通知 - 如果为不同的python版本编译库,则会发生同样的错误。例如,如果共享对象是用于python 3,但是您尝试从python 2导入模块。
答案 2 :(得分:19)
Python并不支持任意C文件作为模块。您必须遵循某些约定,让Python知道您的模块支持哪些功能。
为此,Python将查找init<name>
函数,其中<name>
是模块名称。 Python正在寻找initfizzbuzz
但未能找到它,因此加载模块失败。
除了初始化之外,还需要提供一个详细说明可用函数的结构,并且您的函数需要将Python类型作为参数处理。 Python为您提供了必要的实用程序功能,并定义了使其足够简单。
我强烈建议您关注Extending and Embedding the Python Interpreter tutorial。它教你如何使fizzbuzz
C代码作为Python模块工作。
答案 3 :(得分:5)
您应该定义一个名为init_fizzbuzz
的函数,该函数应包含初始化模块的代码。此函数还应调用Py_InitModule
,以在Python中设置c函数的绑定。有关详细信息,请查看this tutorial。
在你的情况下,你的代码应该适应这样的事情:
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);
}
答案 4 :(得分:3)
做python3 ./yourpythonscript
而不是
python ./yourpythonscript
即使你有python别名为python3
名称必须与编译boost和boost-python完全一致: brew重新安装boost --with-python3 --without-python brew重新安装boost-python --with-python3 --without-python
答案 5 :(得分:2)
如果您使用python 3,那么您需要对代码进行以下更改,
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);
}