web-dev-qa-db-ja.com

コンパイラーはPy_InitModule()を見つけることができません。

私はpython用のC拡張を書こうとしています。以下のコードを使用すると、コンパイラの警告が表示されます。

implicit declaration of function ‘Py_InitModule’

そして、実行時にこのエラーで失敗します:

undefined symbol: Py_InitModule

私は喜びのない解決策を探すために文字通り何時間も費やしました。構文にいくつかのマイナーな変更を試みましたが、メソッドが廃止されていることを示唆する投稿も見つけました。ただし、代替品は見つかりません。

これがコードです:

#include <Python.h>

//a func to calc fib numbers
int cFib(int n)
{
    if (n<2) return n;
    return cFib(n-1) + cFib(n-2);
}


static PyObject* fib(PyObject* self,PyObject* args)
{
    int n;
    if (!PyArg_ParseTuple(args,"i",&n)) 
        return NULL;    
    return Py_BuildValue("i",cFib(n));
}

static PyMethodDef module_methods[] = {
    {"fib",(PyCFunction) fib, METH_VARARGS,"calculates the fibonachi number"},
    {NULL,NULL,0,NULL}
};

PyMODINIT_FUNC initcModPyDem(void)
{
    Py_InitModule("cModPyDem",module_methods,"a module");
}

それが役立つ場合は、私のsetup.pyです:

from distutils.core import setup, Extension

module = Extension('cModPyDem', sources=['cModPyDem.c'])
setup(name = 'packagename', 
    version='1.0',
    description = 'a test package',
    ext_modules = [module])

そしてtest.pyのテストコード:

import cModPyDem

if __name__ == '__main__' :

    print(cModPyDem.fib(200))

どんな助けでも大いに感謝されます。

19
Sam Redway

あなたが持っているコードはPython 2.xではうまく機能しますが、Py_InitModuleはPython 3.xでは使用されなくなりました。現在では、 PyModuleDef 構造を作成し、それへの参照を PyModule_Create に渡します。

構造は次のようになります。

static struct PyModuleDef cModPyDem =
{
    PyModuleDef_HEAD_INIT,
    "cModPyDem", /* 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. */
    module_methods
};

そして、あなたのPyMODINIT_FUNC関数は次のようになります:

PyMODINIT_FUNC PyInit_cModPyDem(void)
{
    return PyModule_Create(&cModPyDem);
}

PyMODINIT_FUNC関数の名前はPyInit_<name>の形式にする必要があることに注意してください。ここで、<name>はモジュールの名前です。

Python 3.xのドキュメントで Extending を読んだ方がいいと思います。最新のPythonで拡張モジュールを構築する方法の詳細な説明があります。

34
iCodez