ImportError:动态模块没有定义init函数(initfizzbuzz)

时间:2014-06-15 02:17:52

标签: python c python-c-extension

我尝试编译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 个答案:

答案 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);
}