使用ctypes处理128位整数 [英] Handling 128-bit integers with ctypes

查看:103
本文介绍了使用ctypes处理128位整数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Python ctypes支持128位整数(当前为__uint128_t)的最佳方法是什么?

What is the best way of supporting 128-bit integers (currently __uint128_t) with Python ctypes?

也许是两个uint64_t的用户定义结构,但这会在需要的地方创建对齐问题。

A user-defined struct of two uint64_t's perhaps, but this will create alignment issues where that is required.

关于ctypes为什么没有扩展为支持128位整数的任何想法?

Any thoughts on why ctypes has not been extended to support 128-bit integers?

推荐答案

如果您真的想使用128位 integers ,那么您就不必担心对齐问题。没有当前的体系结构,也没有运行Python的计算机都支持128位本机整数运算。因此,没有机器会要求或受益于16位字节的128位整数对齐。只需使用用户定义的结构即可。

If you really want to work with 128-bit integers then you don't need to worry about alignment. No current architecture, no machine that Python runs on, supports 128-bit native integer arithmetic. So no machine would require or benefit from having 128-bit integers 16-byte aligned. Just use that user defined struct and you'll be fine.

如果您真正想要的是对128位 vector 的支持,类型,那么您可能需要将它们对齐。也就是说,如果要使用Python代码创建它们并通过引用C / C ++代码来传递它们,则需要将它们对齐。您无法通过值可靠地传递它们,无法获得ctypes以使其在堆栈上正确对齐(如果体系结构ABI要求)。从C / C ++传递到Python的向量大概已经正确对齐了。因此,如果您可以安排所有的向量都用C / C ++代码分配,那么您也可以使用用户定义的结构。

If what you're really asking for is support for 128-bit vector types then you'll probably need to have them aligned. That is, you need them aligned if you're creating them in Python code and passing them by reference to C/C++ code. You can't reliably pass them by value there's no way to get ctypes to align them properly on the stack (if that's required by the architecture ABI). Vectors that are passed from C/C++ to Python will presumably already be aligned properly. So, if you can arrange it so all your vectors are allocated in C/C++ code you should also be fine with your user defined struct.

假设您确实需要在Python代码中创建对齐的矢量,然后我包含了对齐的ctypes数组的代码。我还有一些代码可以将我未包含的其他ctypes类型与合理的代码大小对齐。数组应足以满足大多数目的。这些对齐的阵列有两个限制。如果将它们按值传递给C / C ++函数,或者将它们作为成员包含在结构或联合中,它们将无法正确对齐。您可以使用 * 运算符来创建对齐数组。

Assuming that you do really need to create aligned vectors in Python code then I've included code for aligned ctypes arrays. I also have code to align other ctypes types that I haven't included to the code size reasonable. Arrays should be enough for most purposes. These aligned arrays have a couple of limitations. They won't be aligned properly if you pass them by value to C/C++ functions or if you include them as members in a struct or union. You can make aligned arrays of aligned arrays using the * operator.

使用 aligned_array_type( ctypes-type length alignment 创建新的对齐数组类型。使用 aligned_type( ctypes-type alignment 创建一个已存在的数组类型的对齐版本。

Use aligned_array_type(ctypes-type, length, alignment) to create new aligned array types. Use aligned_type(ctypes-type, alignment) to create an aligned version of an already existing array type.

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)

这篇关于使用ctypes处理128位整数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆