4

Python から C コードを生成するために Cython を試していますが、名前マングリングに問題があるようです。最初にコードを python から c コードに変換し、次に gcc を使用してコードを .so にコンパイルします。C/python API の代わりに cython を使用したい理由は、後でスピードなどのライブラリにしたい、より複雑なクラスでこれを使用するためです (私は行く人を見つけるのに苦労しています)通常は逆なので、Python から C++ に変換します)。以下は、コードを実行しようとする必要があるすべてのコードです (ただし失敗します)。任意の入力をいただければ幸いです。ありがとう!

#hello.pyx
def say_hello():
    print "Hello World!"

#generate the c code
cython -a hello.pyx

#creates the shared library
gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I/usr/include/python2.6 -o libhello.so hello.c

//temp.cpp
#include <iostream>
extern "C" {
void say_hello();
};

using namespace std;

int main(){
    say_hello();
    return 1;
};

#attempt to compile (this is where it fails)
g++ -I/usr/include/python2.6/ -lpython2.6 -L./ -lhello temp.cpp -o temp

エラーメッセージは次のとおりです。

/tmp/ccpKHOMl.o: In function main: temp.cpp:(.text+0x5): undefined reference to say_hello' /tmp/ccpKHOMl.o: 
In function __static_initialization_and_destruction_0(int, int): 
  temp.cpp:(.text+0x33): undefined reference to std::ios_base::Init::Init()  
  temp.cpp:(.text+0x38): undefined reference to std::ios_base::Init::~Init() 
collect2: ld returned 1 exit status 
4

3 に答える 3

3

その方法では、必要な相互運用性を得ることができません。hello.c を開いて調べると、どこにも "static int say_hello" が見つかりません。Cython は、Python で C ライブラリを使用できるように設計されており、C ライブラリで Python を使用できるようには設計されていません。

ドキュメントの here を見ることができますが、残念ながら、このサポートはまだ「担当」のpythonインタープリター用であり、探しているのはその逆です。

http://docs.python.org/release/2.5.4/ext/callingPython.html

「Embedding Python in Another Application」の入門書もあります

http://docs.python.org/2/extending/embedding.html

あなたの要件が何であるかはわかりませんが、場合によっては、データをファイルに正常に書き込み、Python プログラムを呼び出してそれを噛み、別のファイルからの結果を解析できます。物事をメモリに保持するよりも少し醜く遅いですが、多くの状況で完全に機能します。

于 2012-12-11T04:37:21.797 に答える
1

同様の問題が発生しました。まったく同じ問題ではありませんが、関連している可能性があります。

ここに質問を投稿しました: Propagating exceptions through dlsym cython . あなたにとって興味深い部分は、'public' キーワードです。

#hello.pyx
cdef public say_hello():
    print "Hello World!"

それはこのような関数を作成します

# (in the generated C file hello.c)
__PYX_EXTERN_C DL_IMPORT(...) say_hello(...);

編集: 動作する temp.cpp を追加しました:

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

#include "hello.h"

using namespace std;

int main(){
    Py_Initialize();
    inithello();
    say_hello();
    Py_Finalize();
    return 1;
};

コンパイルは以下で行われます:

g++ -I/usr/include/python2.6/ -lpython2.6 -L./ -lhello temp.cpp -c -o temp.o
g++ temp.o -L. -lhello -lpython2.6 -o temp

(興味深いことに、未定義の参照について不平を言って、1つのステップでリンクしません。)これにより、実行時に「Hello world」が正常に出力されます。

注: Py_Initialize() と inithello() が必要です。そうしないと、コードがクラッシュします。「Python.h」を含めず、初期化部分なしで動作させることができませんでした(つまり、あなたが言及したように extern "C" { void sayhello(); } のみを使用しています)。リンクに失敗します。私の質問で示すように、解決策は dlsym を使用して関数を動的にロードすることです。しかし、おそらく、このメソッドを (hello.h ヘッダーで) 正常にエクスポートしようとする別の解決策が存在します。 __PYX_EXTERN_C DL_IMPORT(int) say_hello(void);

于 2013-01-11T14:48:05.297 に答える
0

CMake をお持ちの場合は、CMake を使用して Cython ベースのファイルを生成およびリンクする私のプロジェクトを確認することをお勧めします。

https://github.com/CarloNicolini/cymake

適切な cython インストールを見つけるには、おそらく CMakeLists.txt を編集する必要があります

于 2013-01-11T14:57:31.577 に答える