On Thu, Feb 4, 2016 at 3:33 AM, <jf...@ms4.hinet.net> wrote: > > class DoubleArrayType: > def from_param(self, param): > > [snip] > > DoubleArray = DoubleArrayType() > _avg = _mod.avg > _avg.argtypes = (DoubleArray, ctypes.c_int) > > [snip] > > What confuse me are: > (1) at line: _avg.argtypes = (DoubleArray, ctypes.c_int) > The "DoubleArry" is an instance of the class "DoubleArrayType", > Can it appear at where a type was expected?
ctypes generally (notwithstanding out parameters defined via paramflags) requires only that an object set in argtypes has a from_param callable to check and convert the corresponding argument. Usually classes are set in argtypes, so usually from_param is a classmethod. In this case the author chose to set an instance in argtypes and use an instance method. While unusual, this works all the same. > (2) How the method "from_param" was invoked? I can't see any > mechanism to reach it from the "_avg(values, len(values))" call. A ctypes function pointer is a callable implemented in C. Its tp_call slot function is PyCFuncPtr in Modules/_ctypes/_ctypes.c, which in turn calls _ctypes_callproc in Modules/_ctypes/callproc.c. Here's the snippet of code from _ctypes_callproc that's responsible for calling the from_param converter: converter = PyTuple_GET_ITEM(argtypes, i); v = PyObject_CallFunctionObjArgs(converter, arg, NULL); Note that "argtypes" in the above is a misnomer; it's actually the tuple of from_param converters. Each from_param return value is passed to ConvParam, which handles ctypes objects, integers, strings, and None. If the object isn't of those but has an _as_parameter_ attribute, ConvParam calls itself recursively using the _as_parameter_ value. > _mod = ctypes.cdll.LoadLibrary(_path) Calling ctypes.CDLL directly is preferable since it allows passing parameters such as "mode" and "use_errno". IMO, the ctypes.cdll and ctypes.windll loaders should be avoided in general, especially on Windows, since their attribute-based access (e.g. windll.user32) caches libraries, which in turn cache function-pointer attributes. You don't want function pointer instances being shared across unrelated packages. They may not use compatible prototypes and errcheck functions. Each package, module, or script should create private instances of CDLL, PyDLL, and WinDLL for a given shared library. -- https://mail.python.org/mailman/listinfo/python-list