ctypes.cdll.LoadLibraryを使用してPythonからライブラリをロードするときに無効なELFヘッダ

私はLinux上でgccを使い始めたばかりです。私はチュートリアルのここに従っていますが、 g ++コンパイラ。

hello_fn.cpp

#include 
#include "hello.h"

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

bye_fn.cpp

#include 
#include "hello.h"

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

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 "", line 1, in 
  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 
#include "hello.h"

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

by_fn.cppの変更

#include 
#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

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()

ターミナルで試してみて....

[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

そして私たちの機能の1つとして、私はそれをそのまま変えることはできません。例えば:

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

1 答え

ctypes is for loading shared libraries. ar creates archives of object files, also known as static libraries. You can't load that file with ctypes, it will only be understood by the linker.

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

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

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

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