10

自然なインターフェイスで大きな数値を渡す可能性があるネイティブ ライブラリがあります。約半分が 32 ビット未満であると予想しています。別の 4 分の 1 < 64 ビット。次の 8 番目 < 128 ビット - など、固定長の制限なし。

PyLong_FromUnsignedLongLong() と PyLong_AsUnsignedLongLong() は、値を 1 つのレジスタに収まるように制限できる場合に適しています。

PyLong_FromString() はこれを克服しますが、中間表現が必要になるという望ましくない犠牲を払います。_PyLong_FromByteArray() と _PyLong_AsByteArray() は (この中間表現を単純にすることで) このコストを軽減しますが、先頭のアンダースコアにより、これが移植性の問題につながるのではないかと思います。

longintrepr.h で struct _longobject... を見つけました...これは、内部表現と直接対話する方法である可能性を示唆しています...ただし、この構造に関する詳細なドキュメントがないことは依然としてハードルです。

Python とライブラリの間の最適なスループットをもたらすアプローチはどれですか? 私が見落とした文書はありますか?

4

2 に答える 2

8

アンダースコア プレフィックスは、通常の Python と同様に、C API でもほぼ同じことを意味します。「この関数は実装の詳細が変更される可能性があるため、使用する場合は注意してください」。そのような関数の使用が禁止されているわけではなく、それが特定の目標を達成する唯一の方法である場合 (たとえば、あなたの場合の大幅な効率向上)、その危険性を認識している限り、API を使用してもかまいません。

_PyLong_FromByteArrayAPI が完全に非公開の場合、それはstatic関数になり、完全に文書化されず、longobject.h. 実際、Tim Peters (有名な Python コア開発者)は、その使用を明示的に祝福しています

【ダン・クリステンセン】

私の学生と私は、python long に変換したいバイナリで大きな整数を生成する C 拡張機能を作成しています。ビット数は 32 または 64 よりもはるかに多くなる可能性があります。学生は longobject.h で _PyLong_FromByteArray 関数を見つけました。これはまさに必要なものですが、先頭のアンダースコアは私を警戒させます。この機能を使用しても安全ですか?

Python はそれを内部的に使用するので、そのほうがよい ;-)

Pythonの将来のバージョンでも存在し続けますか?

保証はありません。先頭にアンダースコアが付いているのはそのためです。これは、公式にサポートされており、外部で文書化されており、宣伝されている Python/C API の一部ではありません。たまたまその関数を追加したのは、Python がさまざまな C モジュール間で内部的に何らかの形式の機能を必要としていたためです。これを Python/C API の公式の一部にするとなると、もっと多くの作業が必要になり (私には時間がありませんでした)、永久に新たなメンテナンスの負担が生じます (私はとにかく熱心ではありません ;-))。

実際には、Python の実装のこの部分に触れる人はほとんどいないので、今後何年もの間、この部分がなくなったり、変更されたりすることはないと/予想/します。私が思いつく最大の不安は、負の整数を表す別の方法に基づいて、誰かが他のバイト配列 <-> 長いインターフェイスを「公式」にするための十字軍を開始する可能性があることです。structしかしそれでも、モジュールの "q" フォーマットとpickleモジュールの protocol=2 long serialization フォーマットには 256 の補数表現が必要なため、現在の非公式関数が残ることを期待してい ます。

または、使用すべき他の方法はありますか?

いいえ、それがこれらの関数が最初に発明された理由です;-)

ドキュメントは次のとおりです(Python 3.2.1から):

/* _PyLong_FromByteArray:  View the n unsigned bytes as a binary integer in
   base 256, and return a Python long with the same numeric value.
   If n is 0, the integer is 0.  Else:
   If little_endian is 1/true, bytes[n-1] is the MSB and bytes[0] the LSB;
   else (little_endian is 0/false) bytes[0] is the MSB and bytes[n-1] the
   LSB.
   If is_signed is 0/false, view the bytes as a non-negative integer.
   If is_signed is 1/true, view the bytes as a 2's-complement integer,
   non-negative if bit 0x80 of the MSB is clear, negative if set.
   Error returns:
   + Return NULL with the appropriate exception set if there's not
     enough memory to create the Python long.
*/
PyAPI_FUNC(PyObject *) _PyLong_FromByteArray(
    const unsigned char* bytes, size_t n,
    int little_endian, int is_signed);

「アンダースコアがプレフィックスされた」API である主な理由は、long2 のべき乗ベースの単語の配列としての Python の実装に依存しているためです。これは変更される可能性は低いですが、これに加えて API を実装しているため、後で呼び出し元を Python API の変更から隔離することができます。

于 2013-08-20T02:27:38.760 に答える