Python: указатель ctypes на локальные переменные;как сделать так, чтобы они не освободились? - PullRequest
1 голос
/ 23 июля 2011

У меня есть код, похожий на этот:

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)).

Как я могу убедиться, что созданный там массив ctpes o не освобождается, пока op не освобожден?

Я видел атрибут op._objects, который, кажется, даже существует для этой цели, но доступен только для чтения.

Ответы [ 2 ]

1 голос
/ 23 июля 2011

Это похоже на работу:

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>}
0 голосов
/ 25 июля 2011

Дополнительная итерация не требуется.Просто создайте объект массива и приведите его к необходимому указателю.

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>}
...