【问题标题】:Python: ctypes pointer to local variables; how to ensure they don't get freed?Python:ctypes 指向局部变量的指针;如何确保他们不会被释放?
【发布时间】:2011-07-23 13:23:42
【问题描述】:

我有一些类似的代码:

def castArgToCtype(arg, ctyp):
    if issubclass(ctyp, _ctypes._Pointer): return createPtr(arg, ctyp)
    return ctyp(arg)

def createPtr(arg, ctyp):
    assert isinstance(arg, (list,tuple))
    assert issubclass(ctyp, _ctypes._Pointer)
    o = (ctyp._type_ * (len(arg) + 1))()
    for i in xrange(len(arg)):
        o[i] = castArgToCtype(arg[i], ctyp._type_)
    op = ctypes.cast(ctypes.addressof(o), ctyp)
    # TODO: what when 'o' goes out of scope and freed?
    return op

我称它为createPtr((1,2,3), ctypes.POINTER(ctypes.c_int))

只要op没有被释放,我如何确保我在那里创建的ctpes数组o没有被释放?

我见过op._objects 属性,它似乎是为此目的而存在的,但它是只读的。

【问题讨论】:

  • 您要解决什么问题?为什么你认为这是必要的?
  • @Mark Tolonen:你的问题到底是什么?我的问题是,如何确保o(或底层ctypes 内存块)在createPtr 返回后不被释放。
  • 使用上面的代码,它可能会被释放。因此,在某些时候,您可能会遇到段错误。你当然想避免这种情况。
  • 只是想知道为什么o=(ctypes.c_int*3)(1,2,3) 还不够?
  • @Mark Tolonen:因为就我而言,我需要一个POINTER(c_int)。如果您对我的工作感兴趣,请参阅here

标签: python pointers ctypes


【解决方案1】:

这似乎有效:

import ctypes, _ctypes

def castArgToCtype(arg, ctyp):
    if issubclass(ctyp, _ctypes._Pointer): return createPtr(arg, ctyp)
    return ctyp(arg)

def createPtr(arg, ctyp):
    assert isinstance(arg, (list,tuple))
    assert issubclass(ctyp, _ctypes._Pointer)
    o = (ctyp._type_ * (len(arg) + 1))()
    for i in xrange(len(arg)):
        o[i] = castArgToCtype(arg[i], ctyp._type_)
    op = ctypes.pointer(o)
    op = ctypes.cast(op, ctyp)
    return op

a = createPtr((1,2,3), ctypes.POINTER(ctypes.c_int))
print a, a[0], a[1], a[2], a._objects

输出:

<__main__.LP_c_int object at 0x105dc6680> 1 2 3 {'1': <__main__.c_int_Array_4 object at 0x105dc6560>, '0': {}, 4393297392: <__main__.LP_c_int_Array_4 object at 0x105dc65f0>}

【讨论】:

    【解决方案2】:

    不需要额外的迭代。只需创建数组对象并将其转换为所需的指针即可。

    import ctypes,_ctypes
    def castArgToCtype(arg, ctyp):
        if issubclass(ctyp, _ctypes._Pointer): return createPtr(arg, ctyp)
        return ctyp(arg)
    
    def createPtr(arg, ctyp):
        assert isinstance(arg, (list,tuple))
        assert issubclass(ctyp, _ctypes._Pointer)
        return ctypes.cast((ctyp._type_ * len(arg))(*arg),ctyp)
    
    a = castArgToCtype((1,2,3),ctypes.POINTER(ctypes.c_int))
    print a,a[0],a[1],a[2],a._objects
    

    输出

    <x.LP_c_long object at 0x00EB7760> 1 2 3 {15431440: <ctypes._endian.c_long_Array_3 object at 0x00EB7710>}
    

    【讨论】:

    • 不是createPtr((1,2,3), POINTER(c_int)),但是createPtr(((1,2),(2,3),(3,4)), POINTER(POINTER(c_int)))呢?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-05
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 2014-05-18
    相关资源
    最近更新 更多