web-dev-qa-db-ja.com

定数を.hファイルからpython

この質問に対する簡単な答えを探していましたが、見つからないようです。 Python 2.6 /2.7にまだ含まれていない外部ライブラリには近づかないほうがいいです。

次のような2つのcヘッダーファイルがあります。

//constants_a.h
const double constant1 = 2.25;
const double constant2 = -0.173;
const int constant3 = 13;

.。

//constants_b.h
const double constant1 = 123.25;
const double constant2 = -0.12373;
const int constant3 = 14;

.。

そして、これらの定数をインポートしたいpythonクラスがあります:

#pythonclass.py
class MyObject(object):
    def __init(self, mode):
        if mode is "a":
            # import from constants_a.h, like:
            # self.constant1 = constant1
            # self.constant2 = constant2
        Elif mode is "b":
            # import from constants_b.h, like:
            # self.constant1 = constant1
            # self.constant2 = constant2

.。

定数も使用するcコードがあり、これに似ています。

//computations.c
#include <stdio.h>
#include <math.h>
#include "constants_a.h"

// do some calculations, blah blah blah

定数をヘッダーファイルからPythonクラスにインポートするにはどうすればよいですか?

ヘッダーファイルconstants_a.hとconstants_b.hの理由は、定数を使用してほとんどの計算を行うためにpythonを使用しているためですが、ある時点でCを使用してさらに実行する必要があります最適化された計算。この時点で、ctypesを使用してcコードをPythonにラップしています。定数を更新または変更する必要がある場合に備えて、定数をコードから遠ざけ、コードもよりクリーンにしたいと考えています。私もNumPyを使用していることに注意するのに役立つかどうかはわかりませんが、それ以外に、他の非標準のPython拡張機能はありません。これの設計やアーキテクチャに関する提案も受け付けています。プログラム。

15
Manila Thrilla

正規表現(reモジュール)を使用して、ファイルから必要な情報を解析することをお勧めします。

完全なCパーサーを構築するのは非常に大きなことですが、変数のみを使用し、ファイルが適度に単純/予測可能/制御下にある場合、作成する必要があるのは簡単です。

コメントアウトされたコードなどの「落とし穴」のアーティファクトに注意してください。

11

一般に、Cヘッダーファイルのdefining変数はスタイルが良くありません。ヘッダーファイルはdeclareオブジェクトのみで、適切な「.c」ソースコードファイルの定義を残しておく必要があります。

_extern const whatever_type_t foo;_のようなライブラリグローバル定数を宣言し、Cコードのどこかに定義(または「実装」)(つまり、値を割り当てる)することをお勧めします(これは一度だけ行うようにしてください) )。

とにかく、無視しましょうhowあなたはそれをします。定数をすでに定義し、それらのシンボルを共有オブジェクトファイル「libfoo.so」に表示するとします。 Pythonコードから、libfooで_extern const double pi = 3.1415926;_として定義されているシンボルpiにアクセスするとします。

これで、通常、次のようにctypesを使用してオブジェクトファイルをPythonにロードします。

_>>> import ctypes
>>> libfoo = ctypes.CDLL("path/to/libfoo.so")
_

しかし、ctypesは_libfoo.pi_が関数であり、定数データのシンボルではないと考えていることがわかります。

_>>> libfoo.pi
<_FuncPtr object at 0x1c9c6d0>
_

その値にアクセスするには、かなり厄介なことをする必要があります-ctypesが関数であると考えるものをキャストするbackを数値にキャストします。

_>>> pi = ctypes.cast(foo.pi, ctypes.POINTER(ctypes.c_double))
>>> pi.contents.value
3.1415926
_

Cの専門用語では、これは次のことが起こっていることに漠然と対応しています。_const double pi_がありますが、誰かが関数ポインタを介してのみ使用するように強制します。

_typedef int (*view_anything_as_a_function_t)(void);
view_anyting_as_a_function_t pi_view = &pi;
_

piの値を使用するために、ポインター_pi_view_をどのように処理しますか?それを_const double *_としてキャストバックし、逆参照します:*(const double *)(pi_view)

したがって、これはすべて非常に厄介です。何かが足りないかもしれませんが、これはctypesモジュールの設計によるものだと思います-これは主に外部関​​数呼び出しを行うためのものであり、「外部」データにアクセスするためのものではありません。また、ロード可能なライブラリに純粋なデータシンボルをエクスポートすることはほぼ間違いなくまれです。

また、定数がCマクロ定義のみの場合、これは機能しません。一般に、マクロ定義のデータに外部からアクセスする方法はありません。これらはコンパイル時にマクロ展開され、生成されたライブラリファイルに表示されるシンボルは残りません。ただしマクロ値もCコードにエクスポートします。

15
Cong Ma

ヘッダーに定数値を格納するのではなく、PythonとCプログラムの両方で読み取り可能なある種の構成ファイルを使用することをお勧めします。たとえば、単純なcsv、iniファイル、または独自の単純な形式です。 'key:value'ペア。値の1つを変更するたびにCプログラムを再コンパイルする必要はありません:)

2
Zaur Nasibov

私はエミリオに賛成票を投じますが、担当者が不足しています!

他の非標準ライブラリを避けるように要求しましたが、柔軟性を提供するCython(Cython:C-Extensions for Python www.cython.org/)を参照することをお勧めします。 of PythonコーディングとC/C++でコンパイルされたコードの生の実行速度。

このようにして、すべてに通常のPythonを使用できますが、組み込みのC型を使用してコードの高価な要素を処理できます。次にPythonコードも.cファイルに(または外部Cライブラリ自体をラップするだけで)、バイナリにコンパイルできます。数値ルーチンで最大10倍の高速化を実現しました。NumPyもこれを使用していると思います。

1