web-dev-qa-db-ja.com

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],
)
35
SamuraiT

Pythonは、モジュールとして任意のCファイルをサポートしておらず、サポートできません。モジュールがサポートする機能をPythonに知らせるには、特定の規則に従う必要があります。

そのためには、Pythonはinit<name>関数、ここで<name>はモジュール名です。 Pythonはinitfizzbuzzを探していましたが、見つけられなかったため、モジュールのロードに失敗しました。

初期化子とは別に、使用可能な関数の詳細を示す構造も提供する必要があり、関数は引数としてPython型を処理する必要があります。Python必要なユーティリティ機能と定義を使用して、それを十分に簡単にします。

Python Interpreter tutorial の拡張と埋め込み)に従うことを強くお勧めします。 fizzbuzz CコードをPythonモジュールとして動作するようにします。

20
Martijn Pieters

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

pythonimport libfooを含めると、次のエラーが発生します。

ImportError: dynamic module does not define init function (PyInit_libfoo)

これは、「libhello」と「libfoo」が一致しないためです。

51
philosopher

通知する価値-ライブラリが異なるpythonバージョン用にコンパイルされている場合、同じエラーが発生する可能性があります。たとえば、共有オブジェクトがpython 3 python 2。

25
Ivan Klass

モジュールを初期化するコードを含む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);

}
5
lackadaisical

python3 ./yourpythonscriptを実行します

の代わりに

python ./yourpythonscript

python python3としてエイリアスされている場合でも

名前は、boostおよびboost-pythonをコンパイルする正確な名前にする必要があります。brew restart boost --with-python3 --without-python

3
Aditya Mittal

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);
}
2
kar