6

基礎となるOSライブラリに対して一連のctypes呼び出しを行っています。に保存されている定数値をドキュメントが参照するたびに、私の進行状況はクロールに遅くなります.h。私はそれを追跡し、実際の値が何であるかを把握して、関数に渡すことができるようにする必要があるため、どこかにファイルします。

ctypes を使用してファイルをロードし、.hすべての定数にアクセスする方法はありますか?

4

1 に答える 1

6

いいえ。

の初期バージョンには、ヘッダー ファイルを解析して定数値を取得し、プロトタイプを/宣言に変換するctypesというモジュールが付属していました。しかし、私が知る限り、これは完成することはなく、stdlib に含まれる前にパッケージから削除されました。codegeneratorrestypeargtypes

ソースを掘り下げて、より複雑なプロトタイプのものをスキップしながら、定数のものを引き出すことができます。


ただし、私が通常行っている方法は、独自のジェネレーターを作成することです。

たとえば、セットアップ プロセスの一部として次のスクリプトを実行します。

constants = {}
with open('foo.h') as infile:
    for name, value in re.findall(r'#define\s+(\w+)\s+(.*)', infile):
        try:
            constants[name] = ast.literal_eval(value)
        except Exception as e:
            pass # maybe log something
with open('_foo_h.py', w) as outfile:
    outfile.write(repr(constants))

その後、foo.pyできますfrom _foo_h import *

これに完全な正規表現を書くのは非常に難しく、おそらく不可能です。特定のプロジェクトで実際に関心のあるヘッダーで機能するヘッダーを作成するのは非常に簡単です。実際、多くの場合、上記のもの、またはコメントをスキップするもので十分です。

しかし、これがうまくいかない場合もあります。たとえば、ヘッダー ファイルは#define FOO_SIZE 864 ビット ビルド#define FOO_SIZE 4用と 32 ビット ビルド用です。それをどのように処理しますか?

そのためには、コンパイラにそれを行うように依頼します。ほとんどのコンパイラには、すべてのアクティブな定義を取得するのに十分なだけファイルを前処理する方法があります。一部のコンパイラは、他のすべてをスキップして、適切な形式でマクロ定義をダンプすることさえできます。、プリプロセス、およびダンプ マクロgccなどのフラグ互換コンパイラを使用します。そう:clang-E-dM

macros = subprocess.check_output(['gcc', '-dM', '-E', '-', 'foo.h'])
for line in macros.splitlines():
    try:
        _, name, value = line.split(None, 2)
        constants[name] = ast.literal_eval(value)
    except Exception as e:
        pass # again, do something nicer

の結果のように、適切に定義されるものを制御するために、いくつかの追加のコンパイラ フラグを渡したい場合がありpkgconfig foo --cflagsます。

これにより、(再帰的に) インクルードするもので定義されたマクロfoo.hと、gcc の組み込みマクロも提供されます。それらのそれぞれが必要な場合とそうでない場合があります。69105 gcc flags のどこかに、それを制御する方法があると思いますが、覚えていません。


これらのどちらも、次のような定数変数または列挙型を取得しないことに注意してください。

static const int SPAM_SPAM_SPAM = 73;
enum {
    kSPAM = 1,
    kEGGS
};

より困難になる解析。のような実際の C99 パーサーを使用するか、代わりに のpycparserようなものの出力を解析する必要があります。しかし、それでも、少しロジックを書かないと、それが 2 であるとは言えません。gccxmlgcc -EkEGGS

また、C++ を扱いたい場合は、さらに悪いことに、constexpr と静的クラス メンバーとユーザー定義リテラルの場合はどうなりますか?</p>


または…使用する必要がありますctypesか?

CFFIは、Python から C コードを呼び出す別の方法を提供します。これにより、これがはるかに簡単になります。

CythonPython 拡張モジュールにコンパイルされる C にコンパイルされるほぼ Python コードを記述でき、ヘッダー ファイルを直接インクルードできます。

また、拡張モジュールを介して Python に値を簡単にエクスポートできるようにするさまざまなバインディング ジェネレーター (SWIG など) またはバインディング書き込みライブラリ (boost::python など) もあります。

于 2013-09-12T22:46:18.590 に答える