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],
)
Pythonは、モジュールとして任意のCファイルをサポートしておらず、サポートできません。モジュールがサポートする機能をPythonに知らせるには、特定の規則に従う必要があります。
そのためには、Pythonはinit<name>
関数、ここで<name>
はモジュール名です。 Pythonはinitfizzbuzz
を探していましたが、見つけられなかったため、モジュールのロードに失敗しました。
初期化子とは別に、使用可能な関数の詳細を示す構造も提供する必要があり、関数は引数としてPython型を処理する必要があります。Python必要なユーティリティ機能と定義を使用して、それを十分に簡単にします。
Python Interpreter tutorial の拡張と埋め込み)に従うことを強くお勧めします。 fizzbuzz
CコードをPythonモジュールとして動作するようにします。
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バージョン用にコンパイルされている場合、同じエラーが発生する可能性があります。たとえば、共有オブジェクトがpython 3 python 2。
モジュールを初期化するコードを含む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);
}
python3 ./yourpythonscriptを実行します
の代わりに
python ./yourpythonscript
python python3としてエイリアスされている場合でも
名前は、boostおよびboost-pythonをコンパイルする正確な名前にする必要があります。brew restart boost --with-python3 --without-python
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);
}