Мне было интересно, можно ли подклассифицировать различные типы ctypes. Я попытался написать простой пример, но есть одна (или две) вещи, которые я не понимаю.Подклассы типов типов
from ctypes import *
class my_c_int(c_int):
pass
# def __new__(*args):
# print "Hello from __new__" # why is this not called?
libc = cdll.LoadLibrary("libc.dylib")
printf = libc.printf
# printf.restype = c_int # prints "14"
printf.restype = my_c_int # prints "<my_c_int object at 0x...>"
print printf("Hello, %s\n", "World!")
Почему не my_c_int
возвращает тот же тип, что и исходный c_int
, а именно int
? Можно ли это сделать? Если я пишу print printf(...).value
, он работает. Можно ли автоматически вернуть .value
для my_c_int
?
PS: Btw., Почему метод __new__
не называется?
Edit:
Рассмотрим другой пример, из документации:
from ctypes import *
libc = cdll.LoadLibrary("libc.dylib")
IntArray5 = c_int * 5
ia = IntArray5(5, 1, 7, 33, 99)
qsort = libc.qsort
qsort.restype = None
CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
def py_cmp_func(a, b):
print "py_cmp_func", a[0], b[0]
return a[0] - b[0]
cmp_func = CMPFUNC(py_cmp_func)
qsort(ia, len(ia), sizeof(c_int), cmp_func)
Хорошо, это работает. Мой вопрос: возможно ли изменить аргументы, получаемые функцией CMPFUNC
? Можно ли это сделать, используя какой-то тип/тип подкласса типа?
Например, я хотел бы передать py_cmp_func
целые числа непосредственно (а не указатели). Я могу сделать:
from ctypes import *
libc = cdll.LoadLibrary("libc.dylib")
IntArray5 = c_int * 5
ia = IntArray5(5, 1, 7, 33, 99)
qsort = libc.qsort
qsort.restype = None
CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
def auxiliary(a, b):
return py_cmp_func(a[0], b[0])
def py_cmp_func(a, b):
print "py_cmp_func", a, b
return a - b
cmp_func = CMPFUNC(auxiliary)
qsort(ia, len(ia), sizeof(c_int), cmp_func)
Это тоже работает, но это не то, что я после. Возможно ли иметь такое поведение без функции auxiliary
? Вид:
from ctypes import *
libc = cdll.LoadLibrary("libc.dylib")
IntArray5 = c_int * 5
ia = IntArray5(5, 1, 7, 33, 99)
qsort = libc.qsort
qsort.restype = None
class my_int_pointer(object):
@classmethod
def from_param(cls, obj): # not sure it `from_param` is the right place
# in any case, it will not be called, anyway...
return cast(obj, POINTER(c_int))[0]
CMPFUNC = CFUNCTYPE(c_int, my_int_pointer, POINTER(c_int))
def py_cmp_func(a, b):
print "py_cmp_func", a, b[0]
return a - b[0]
cmp_func = CMPFUNC(py_cmp_func)
qsort(ia, len(ia), sizeof(c_int), cmp_func)
но это не работает.
Короче говоря, я хотел бы знать, как настроить вход и выход функции ctypes.
'__new__' в вашем примере вызывается для меня (когда не закомментирована). – 101
@figs, на котором Python вы его используете? Я пробовал как CPython 2.7.5, так и PyPy 2.4.0 без успеха. –
'getfunc' пропускается для подкласса. Вызов этого просто вернул бы обычный объект Python, так зачем беспокоиться? Тем не менее, методы '__new__' и' __init__' подкласса также не вызываются, поэтому вы не можете настроить результат. Он выделяет объект напрямую, вызывая тип 'tp_alloc'. Затем он копирует результат в буфер объекта. – eryksun