On Wed, Oct 5, 2016 at 9:03 PM, Michael Felt <mich...@felt.demon.nl> wrote: > >> +80 args = (1, "name", None), (2, "buff", None), (1, "size", >> 0), (1, "count", 1) > > error #1. paramater type 2 (the buffer might be where data is being put, but > for the call, the pointer is INPUT)
An output parameter (type 2) has ctypes implicitly create the buffer and insert it in the argument list. It gets returned as the call's result. Here's a contrived example: class Buf(ctypes.Structure): _fields_ = (('value', ctypes.c_char * 100),) LP_Buf = ctypes.POINTER(Buf) proto = ctypes.CFUNCTYPE(ctypes.c_int, LP_Buf, ctypes.c_char_p, ctypes.c_int) flags = ((2, 'buf'), (1, 'fmt'), (1, 'arg', 42)) sprintf = proto(('sprintf', ctypes.CDLL(None)), flags) >>> r = sprintf(b'The answer is %d.') >>> r.value b'The answer is 42.' This works best when combined with an errcheck function. This lets you see the actual arguments that were passed in the call and the original result: def errcheck(result, func, args): print('result:', result) print('args:', args) return args sprintf.errcheck = errcheck >>> r = sprintf(b'The answer is %d.') result: 17 args: (<__main__.Buf object at 0x7fede840bb70>, b'The answer is %d.', 42) When the errcheck function returns "args", this tells ctypes to continue with its normal post-processing, so instead of the actual 17 result, it returns the "buf" output parameter: >>> r.value b'The answer is 42.' Notice that I declared the output parameter's type as a pointer type, but ctypes is smart enough to create a Buf instance for me instead of just a pointer. Also, because the argument type is a pointer type, its from_param method implicitly passes the Buf instance by reference. > class perfstat_xxx: > def init(self): > # AIX member in an archive > _perflib = ctypes.CDLL("libperfstat.a(shr_64.o)") > _fn_xxx = _perflib.xxx > # ALL AIX perfstat routines have 4 arguments: > # (name, buff, sizeof_buff, count) > # the buff is a pointer to where the information will be stored > _fn = CFUNCTYPE(c_int, c_void_p, POINTER(xxx_t), c_int, c_int) > _args = ((1, "name", None), (1, "buff", None), (1, "size", 0), > (1, "count", 1)) > _xxx = _fn(("xxx", _fn_xxx), _args) You should really do this work at the class or module level. Every time this init() method is called, you're needlessly incrementing the reference count on the "libperfstat.a(shr_64.o)" shared library and needlessly creating and instantiating the function pointer type. -- https://mail.python.org/mailman/listinfo/python-list