2011-11-25 25 views
1

Linuxでgccを使い始めたばかりです。チュートリアルhereに従っていますが、g ++コンパイラを使用しています。私は、シェルで次のように実行しますctypes.cdll.LoadLibraryを使用してPythonからライブラリをロードするときに無効なELFヘッダ

hello_fn.cpp

#include <stdio.h> 
#include "hello.h" 

void 
hello (const char * name) 
{ 
    printf ("Hello, %s!\n", name); 
} 

#include <stdio.h> 
#include "hello.h" 

void 
bye (void) 
{ 
    printf ("Goodbye!\n"); 
} 

bye_fn.cpp hello.h

void hello (const char * name); 
void bye (void); 

$ g++ -Wall -c hello_fn.cpp 
$ g++ -Wall -c bye_fn.cpp 
$ ar cr libhello.a hello_fn.o bye_fn.o 

それから私のpythonから、次の試してください。

Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24) 
[GCC 4.5.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import ctypes 
>>> test = ctypes.cdll.LoadLibrary(r'/home/oob/development/libtest/libhello.a') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.7/ctypes/__init__.py", line 431, in LoadLibrary 
    return self._dlltype(name) 
    File "/usr/lib/python2.7/ctypes/__init__.py", line 353, in __init__ 
    self._handle = _dlopen(self._name, mode) 
OSError: /home/jeff/development/libtest/libhello.a: invalid ELF header 

私の考えでは、C++で一部の機能を書くとPythonから呼び出すことでした。何か案は?

更新:私は物事を「働く」ことができました。 Cat Plus Plusが語ったところによると、私は新しいコードのためにこの方向を向いていないかもしれませんが、私はWindowsからLinuxに移植していた大規模な従来のC++ライブラリでこれを動作させることができました。このライブラリから長時間実行される関数を呼び出すためにフロントエンドが必要なので、私はPythonが最も簡単かもしれないと考えました。関数はたくさんの出力を生成し、整数の戻りコードしか返さないので、おそらくCat Plus Plusが言っていた "痛い"ものを避けることができます。

ここに私がしたことがあります。

修飾hello_fn.cpp

#include <stdio.h> 
#include "hello.h" 

extern "C" void 
bye (void) 
{ 
    printf ("Goodbye!\n"); 
} 

修飾hello.h

extern "C" int hello (void); 
extern "C" void bye (void); 

buildscript.sh

#!/bin/bash 

rm *.o 
rm *.so 

g++ -fpic -g -c -Wall hello_fn.cpp 
g++ -fpic -g -c -Wall bye_fn.cpp 
#make a shared library, not a static library (thanks cat plus plus) 
g++ -shared -o libhello.so hello_fn.o bye_fn.o 
by_fn.cpp修飾

#include <stdio.h> 
#include "hello.h" 

extern "C" int 
hello (void) 
{ 
    return 16; 
}                     

test.pyは

#!/usr/bin/python 

import ctypes 

c = ctypes.cdll.LoadLibrary(r'/home/jeff/development/libtest/libhello.so') 
a = c.hello() 
print 'hello was ' + str(a) 
c.bye() 

ターミナルでそれを試してみてください3210

....

[email protected]:~/development/libtest$ ./build_script.sh 
[email protected]:~/development/libtest$ python test.py 
hello was 16 
Goodbye! 

本当に(書いた人のおかげで任意のWindows固有のC++のものを使用していない当社のレガシーライブラリーそのコード)、それは非常に簡単なポートされています。 extern "C"を使って関数を公開するいくつかの関数がありました。ポートのために、私は次のように変更作られています

#ifdef LINUX 
#define __stdcall 
#endif 
#ifdef WINDOWS 
#define __stdcall __stdcall 
#endif 

をそして、我々の機能の一つのために、私は例えば、そのままそれを残すことができます。

extern "C" long __stdcall reform_proj { 
    //do a bunch of stuff 
    return 0; 
} 

答えて

4

​​共有ライブラリをロードするためです。 arは、スタティックライブラリとも呼ばれるオブジェクトファイルのアーカイブを作成します。そのファイルを​​でロードすることはできません。リンカーによってのみ理解されます。

別の問題は、C++共有ライブラリを​​経由で使用することは、絶対に不可能ではないにしても痛いことです。ただしないでください。代わりにCythonを使用して、C++コードとインターフェイスする適切なPython拡張を記述します(次に、静的または動的にリンクすることができます)。

もう1つのオプションはBoost.Pythonですが、文書化されていませんが、別の言語で書かれたラッパーを使用するのではなく、C++コードで直接Pythonモジュールを定義する利点があります。

第3はSWIGですが、私はそれを一度も使用していないので、実際にどの程度うまく機能しているかは分かりません。

+0

ありがとうございました。静的対共有は私が始めなければならないものです。私がこの小さな例のために働いていた方法については、私のアップデートを見てください。私は将来私が書くことを予定しているコードについては、あなたのアドバイス(cythonについて)を必ず取っていきます。 – oob

関連する問題