2
\$\begingroup\$

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.
    @classmethod
    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)]
    drop_bng_array(array)
    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).

\$\endgroup\$

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.