Nếu bạn thực sự muốn làm việc với các số nguyên 128 bit thì bạn không cần phải lo lắng về căn chỉnh. Không có kiến trúc hiện tại, không có máy mà Python chạy trên, hỗ trợ số học nguyên nguyên 128 bit. Vì vậy, không có máy nào yêu cầu hoặc hưởng lợi từ việc có các số nguyên 128 bit được căn chỉnh 16 byte. Chỉ cần sử dụng cấu trúc do người dùng định nghĩa đó và bạn sẽ ổn.
Nếu những gì bạn thực sự yêu cầu là hỗ trợ cho các loại 1282 bit vector thì có thể bạn sẽ cần phải căn chỉnh chúng. Tức là, bạn cần chúng liên kết nếu bạn đang tạo chúng trong mã Python và chuyển chúng bằng tham chiếu đến mã C/C++. Bạn không thể vượt qua chúng một cách đáng tin cậy bởi giá trị không có cách nào để có được ctypes để sắp xếp chúng đúng cách trên stack (nếu đó là yêu cầu của kiến trúc ABI). Các vectơ được chuyển từ C/C++ sang Python có lẽ đã được căn chỉnh đúng cách. Vì vậy, nếu bạn có thể sắp xếp nó để tất cả các vectơ của bạn được cấp phát trong mã C/C++, bạn cũng nên sử dụng cấu trúc do người dùng định nghĩa của bạn.
Giả sử bạn thực sự cần phải tạo các vectơ liên kết trong mã Python sau đó tôi đã bao gồm mã cho các mảng ctypes liên kết. Tôi cũng có mã để sắp xếp các loại ctypes khác mà tôi chưa đưa vào kích thước mã hợp lý. Mảng nên là đủ cho hầu hết các mục đích. Các mảng liên kết này có một số hạn chế. Chúng sẽ không được căn chỉnh đúng cách nếu bạn chuyển chúng theo giá trị tới các hàm C/C++ hoặc nếu bạn gộp chúng thành các thành viên trong một cấu trúc hoặc liên kết. Bạn có thể tạo các mảng liên kết của các mảng được liên kết bằng cách sử dụng toán tử *
.
Sử dụng aligned_array_type(ctypes-type, length, alignment)
để tạo các loại mảng được căn chỉnh mới. Sử dụng aligned_type(ctypes-type, alignment)
để tạo phiên bản được sắp xếp của loại mảng đã tồn tại.
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)
Cấu trúc đóng gói (_pack_ = 1) sẽ giải quyết vấn đề căn chỉnh ít nhất. – epx
Không thực sự, các vectơ này cần phải được giữ ở bộ nhớ liên kết với 16 byte để có hiệu suất tốt nhất. – Fil
Lưu ý: '__uint128_t' dường như là phần mở rộng GCC: http://stackoverflow.com/a/18531871/2419207 – iljau