Cython経由でCからPythonコードを呼び出す 質問する

Cython経由でCからPythonコードを呼び出す 質問する

そこで、C から Cython 経由で Python コードを呼び出したいのですが、C から Cython コードを呼び出すことはできました。また、Cython から Python コードを呼び出すこともできます。しかし、すべてを合計すると、いくつかが欠けています。

これが私の Python コードです ( quacker.pyx)。

def quack():
    print "Quack!"

これが私の Cython「ブリッジ」(caller.pyx)です。

from quacker import quack

cdef public void call_quack():
    quack()

そして、これが C コードです ( main.c)。

#include <Python.h>
#include "caller.h"

int main() {
  Py_Initialize();
  initcaller();
  call_quack();
  Py_Finalize();
  return 0;
}

これを実行すると、次の例外が発生します:

Exception NameError: "name 'quack' is not defined" in 'caller.call_quack' ignored

私が疑っている欠けている部分:

  • 電話していないinitquacker()
  • 含めていないquacker.h
  • Cythonは何も生産しなかったquacker.h-only quacker.c
  • caller.cインポートquacker.hも呼び出しも行いませんinitquacker()

私がやろうとしていることが本当に可能かどうかはわかりませんが、できるはずだと思っています。何かご意見があればぜひお聞かせください。

編集:

cython 化 / コンパイル / リンク / 実行の方法は、次のとおりです。

$ cython *.pyx
$ cc -c *.c -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7
$ cc -L/System/Library/Frameworks/Python.framework/Versions/2.7/lib -L/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config -lpython2.7 -ldl *.o -o main
$ ./main

ベストアンサー1

quacker.pyxを に名前変更するとquacker.py、実際にはすべて正しくなります。唯一の問題は、プログラムが現在のディレクトリで Python モジュールを検索しないため、次のような出力になることです。

Exception NameError: "name 'quack' is not defined" in 'caller.call_quack' ignored

ただし、現在のディレクトリを PYTHONPATH 環境変数に追加すると、出力は期待どおりのものになります。

$ PYTHONPATH=".:$PYTHONPATH" ./main 
Quack!

Pythonシェルを実行すると、ドキュメンテーション現在のディレクトリ (またはスクリプトを含むディレクトリ) はsys.path自動的に変数に追加されますが、を使用して簡単なプログラムを作成するとPy_InitializePy_Finalizeこれは行われないようです。 PYTHONPATH 変数はsys.pathPython 変数を設定するためにも使用されるため、上記の回避策により正しい結果が得られます。

あるいは、文字列として指定された Python コードを実行するだけでPy_Intialize、次の行の下に空の文字列を追加することもできます。sys.path

PyRun_SimpleString("import sys\nsys.path.insert(0,'')");

再コンパイル後、実行するだけ./mainで動作するはずです。

編集

質問で指定されているとおりに、つまりファイル名を変更せずにコードを実行すると何が起こるかを見るのは、実際に興味深いことですquacker.pyx。その場合、initcaller()関数はモジュールをインポートしようとしますquackerが、quacker.pyまたはがquacker.pyc存在しないため、モジュールが見つからず、initcaller()関数はエラーを生成します。

現在、このエラーは例外を発生させるという Python の方法で報告されています。しかし、main.cファイル内のコードはこれをチェックしていません。私はこの分野の専門家ではありませんが、私のテストでは以下のコードを追加するとinitcaller()うまくいったようです。

if (PyErr_Occurred())
{
    PyErr_Print();
    return -1;
}

プログラムの出力は次のようになります。

Traceback (most recent call last):
  File "caller.pyx", line 1, in init caller (caller.c:836)
    from quacker import quack
ImportError: No module named quacker

initquacker()関数を呼び出すことによって前に initcaller()モジュール名はquackerすでに登録されているため、内部で実行されるインポート呼び出しでは、initcaller()すでにロードされていることが検出され、呼び出しは成功します。

おすすめ記事