Pythonのctypesで128ビット整数(現在は__uint128_t)をサポートする最良の方法は何ですか?ctypesを持つ128ビット整数の扱い
おそらく2つのuint64_tのユーザー定義構造体ですが、これは必要な箇所で整列問題を作成します。
なぜctypesが128ビット整数をサポートするように拡張されていないのか?
Pythonのctypesで128ビット整数(現在は__uint128_t)をサポートする最良の方法は何ですか?ctypesを持つ128ビット整数の扱い
おそらく2つのuint64_tのユーザー定義構造体ですが、これは必要な箇所で整列問題を作成します。
なぜctypesが128ビット整数をサポートするように拡張されていないのか?
実際に128ビットのの整数を使用したい場合、アラインメントについて心配する必要はありません。現在のアーキテクチャはなく、Pythonを実行するマシンもなく、128ビットのネイティブ整数算術をサポートしています。だから、128ビットの整数を16バイトに整列させることを必要としたり、恩恵を受けるマシンはありません。そのユーザー定義の構造体を使用すれば、うまくいくでしょう。
あなたが本当に求めているのは、128ビットのベクトルタイプのサポートであれば、おそらくそれらを整列させる必要があります。つまり、Pythonコードで作成し、C/C++コードを参照して渡す場合は、それらを整列させる必要があります。値を確実に渡すことはできません。スタック上にctypesを適切に配置する方法はありません(アーキテクチャABIで必要な場合)。 C/C++からPythonに渡されるベクトルはおそらく既に適切に整列されています。だから、すべてのベクトルがC/C++コードで割り当てられるように配列することができれば、ユーザー定義の構造体もうまくいくはずです。
実際には、Pythonコードで整列したベクトルを作成する必要があると仮定し、整列されたctypes配列のコードを含めました。私は、他のctypes型を、コードサイズに合わないものに合わせるためのコードも用意しています。配列はほとんどの目的に十分でなければなりません。これらの整列された配列にはいくつかの制限があります。 C/C++関数に値を渡したり、構造体または共用体のメンバーとしてそれらを含めると、それらは正しく整列されません。 *
演算子を使用して、配列された配列の配列を整列させることができます。
aligned_array_type(ctypes-type, length, alignment)
を使用すると、新しい配列型を作成できます。既に存在するアレイタイプの整列バージョンを作成するにはaligned_type(ctypes-type, alignment)
を使用してください。
import ctypes
ArrayType = type(ctypes.Array)
class _aligned_array_type(ArrayType):
def __mul__(self, length):
return aligned_array_type(self._type_ * self._length_,
length, self._alignment_)
def __init__(self, name, bases, d):
self._alignment_ = max(getattr(self, "_alignment_", 1),
ctypes.alignment(self))
def _aligned__new__(cls):
a = cls._baseclass_.__new__(cls)
align = cls._alignment_
if ctypes.addressof(a) % align == 0:
return a
cls._baseclass_.__init__(a) # dunno if necessary
ctypes.resize(a, ctypes.sizeof(a) + align - 1)
addr = ctypes.addressof(a)
aligned = (addr + align - 1) // align * align
return cls.from_buffer(a, aligned - addr)
class aligned_base(object):
@classmethod
def from_address(cls, addr):
if addr % cls._alignment_ != 0:
raise ValueError, ("address must be %d byte aligned"
% cls._alignment_)
return cls._baseclass_.from_address(cls, addr)
@classmethod
def from_param(cls, addr):
raise ValueError, ("%s objects may not be passed by value"
% cls.__name__)
class aligned_array(ctypes.Array, aligned_base):
_baseclass_ = ctypes.Array
_type_ = ctypes.c_byte
_length_ = 1
__new__ = _aligned__new__
_aligned_type_cache = {}
def aligned_array_type(typ, length, alignment = None):
"""Create a ctypes array type with an alignment greater than natural"""
natural = ctypes.alignment(typ)
if alignment == None:
alignment = typ._alignment_
else:
alignment = max(alignment, getattr(typ, "_alignment_", 1))
if natural % alignment == 0:
return typ * length
eltsize = ctypes.sizeof(typ)
eltalign = getattr(typ, "_alignment_", 1)
if eltsize % eltalign != 0:
raise TypeError("type %s can't have element alignment %d"
" in an array" % (typ.__name__, alignment))
key = (_aligned_array_type, (typ, length), alignment)
ret = _aligned_type_cache.get(key)
if ret == None:
name = "%s_array_%d_aligned_%d" % (typ.__name__, length,
alignment)
d = {"_type_": typ,
"_length_": length,
"_alignment_": alignment}
ret = _aligned_array_type(name, (aligned_array,), d)
_aligned_type_cache[key] = ret
return ret
def aligned_type(typ, alignment):
"""Create a ctypes type with an alignment greater than natural"""
if ctypes.alignment(typ) % alignment == 0:
return typ
if issubclass(typ, ctypes.Array):
return aligned_array_type(typ._type_, typ._length_,
alignment)
else:
raise TypeError("unsupported type %s" % typ)
パックされた構造体(_pack_ = 1)は、少なくとも整列の問題を解決します。 – epx
実際には、これらのベクトルは、最高のパフォーマンスを得るために16バイトのメモリに保持する必要があります。 – Fil
注: '__uint128_t'はGCCエクステンションのようです:http://stackoverflow.com/a/18531871/2419207 – iljau