I'm trying to figure out whether I can speed up passing large int and float lists to my foreign function:

from ctypes import cdll, c_uint32, c_float, Structure, c_void_p, cast, c_size_t, POINTER

lib = cdll.LoadLibrary('whatever.dylib')

class _BNG_FFITuple(Structure):
    _fields_ = [("a", c_uint32),
                ("b", c_uint32)]

class _BNG_FFIArray(Structure):
    _fields_ = [("data", c_void_p),
                ("len", c_size_t)]
    # Allow implicit conversions from a sequence of 32-bit unsigned
    # integers.
    def from_param(cls, seq):
        return seq if isinstance(seq, cls) else cls(seq)

    # Wrap sequence of values. You can specify another type besides a
    # 32-bit unsigned integer.
    def __init__(self, seq, data_type = c_float):
        array_type = data_type * len(seq)
        raw_seq = array_type(*seq)
        self.data = cast(raw_seq, c_void_p)
        self.len = len(seq)

# A conversion function that cleans up the result value to make it
# nicer to consume.
def _bng_void_array_to_tuple_list(array, _func, _args):
    res = cast(array.data, POINTER(_BNG_FFITuple * array.len))[0]
    res_list = [(i.a, i.b) for i in iter(res)]
    return res_list

convert_bng = lib.convert_to_bng_threaded
convert_bng.argtypes = (_BNG_FFIArray, _BNG_FFIArray)
convert_bng.restype = _BNG_FFIArray
convert_bng.errcheck = _bng_void_array_to_tuple_list

This means I can call convert_bng with two lists, like so:

convert_bng(float_list, another_float_list)

and get a list of int tuples back. But I'm wondering whether I can send the _BNG_FFIArrays by reference instead, and whether that will be faster (I'm obviously consuming them on the C side, but not changing their values).


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.