How this C function was called through ctypes this way?

jfong at jfong at
Thu Feb 4 04:33:02 EST 2016

Here is an example from "Python Cookbook, Third Edition(by David Beazley and Brian K. Jones)" Chapter 15.1. "Accessing C Code Using ctypes"

import ctypes
# Try to locate the .so file in the same directory as this file
_mod = ctypes.cdll.LoadLibrary(_path)
# void avg(double *, int n)
# Define a special type for the 'double *' argument
class DoubleArrayType:
    def from_param(self, param):
        typename = type(param).__name__
        if hasattr(self, 'from_' + typename):
            return getattr(self, 'from_' + typename)(param)
        elif isinstance(param, ctypes.Array):
            return param
            raise TypeError("Can't convert %s" % typename)

    # Cast from array.array objects
    def from_array(self, param):
    # Cast from lists
    def from_list(self, param):
        val = ((ctypes.c_double)*len(param))(*param)
        return val

    # Cast from a numpy array
    def from_ndarray(self, param):

DoubleArray = DoubleArrayType()
_avg = _mod.avg
_avg.argtypes = (DoubleArray, ctypes.c_int)
_avg.restype = ctypes.c_double

def avg(values):
    return _avg(values, len(values))


The followings was quoted from the book which explain how it does:
"The DoubleArrayType class shows how to handle this situation. In this class, a single method from_param() is defined. The role of this method is to take a single parameter and narrow it down to a compatible ctypes object (a pointer to a ctypes.c_double, in the example). Within from_param(), you are free to do anything that you wish. In the solution, the typename of the parameter is extracted and used to dispatch to a more specialized method. For example, if a list is passed, the typename is list and a method from_list() is invoked."

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? 
(2) How the method "from_param" was invoked? I can't see any mechanism to reach it from the "_avg(values, len(values))" call.

Best Regards,
Jach Fong

More information about the Python-list mailing list