파이썬 ctypes에서 128 비트 정수 (현재 __uint128_t)를 지원하는 가장 좋은 방법은 무엇입니까?ctypes가있는 128 비트 정수 처리
두 개의 uint64_t 구조로 사용자 정의 된 구조 일 수 있지만 필요한 경우 위치 맞춤 문제가 발생합니다.
ctypes가 128 비트 정수를 지원하도록 확장되지 않은 이유에 대한 의견이 있으십니까?
파이썬 ctypes에서 128 비트 정수 (현재 __uint128_t)를 지원하는 가장 좋은 방법은 무엇입니까?ctypes가있는 128 비트 정수 처리
두 개의 uint64_t 구조로 사용자 정의 된 구조 일 수 있지만 필요한 경우 위치 맞춤 문제가 발생합니다.
ctypes가 128 비트 정수를 지원하도록 확장되지 않은 이유에 대한 의견이 있으십니까?
실제로 128 비트 정수으로 작업하려면 정렬에 대해 걱정할 필요가 없습니다. 현재 아키텍처 나 Python이 실행되지 않는 머신은 128 비트 원시 정수 연산을 지원하지 않습니다. 따라서 어떤 기계도 16 비트 정렬 된 128 비트 정수를 필요로하거나 이익을 얻을 수 없습니다. 그냥 사용자 정의 구조체를 사용하면 괜찮을거야.
당신이 진짜로 요구하는 무엇이 128 비트 벡터 유형을 지원하는 경우에 아마 당신은 그 (것)들을 일렬로 세워야 할 것입니다. 즉, 파이썬 코드로 작성하고 C/C++ 코드를 참조하여 전달하는 경우 정렬해야합니다. 값으로 안정적으로 전달할 수는 없습니다. 스택에서 적절하게 정렬 할 수있는 ctypes를 얻을 수있는 방법이 없습니다 (아키텍처 ABI에서 필요하다면). C/C++에서 Python으로 전달되는 벡터는 아마도 이미 제대로 정렬되어있을 것입니다. 그래서, 모든 벡터가 C/C++ 코드로 할당되도록 배열 할 수 있다면 사용자 정의 구조체로도 잘되어야합니다.
정렬 된 벡터를 파이썬 코드로 작성해야한다고 가정하면 정렬 된 ctypes 배열에 대한 코드가 포함되어 있습니다. 또한 합리적인 코드 크기에 포함시키지 않은 다른 ctypes 형식을 정렬하는 코드도 있습니다. 배열은 대부분의 목적을 위해 충분해야합니다. 정렬 된 배열에는 몇 가지 제한이 있습니다. C/C++ 함수에 값을 전달하거나 struct 또는 union에 멤버로 포함하는 경우 제대로 정렬되지 않습니다. *
연산자를 사용하여 정렬 된 배열의 정렬 된 배열을 만들 수 있습니다.
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