Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to interface a NumPy complex array with C function using ctypes?

I have a function in C that takes an array of complex floats and does calculations on them in-place.:

/* foo.c */
void foo(cmplx_float* array, int length) {...}

The complex float struct looks like this:

typedef struct cmplx_float {
   float real;
   float imag;
} cmplx_float ;

I need to call that function in python using ctypes. In Python I have an Numpy 1-D ndarray of complex64 elements.

I have also made a class derived from ctypes.Structure:

class c_float(Structure):
   _fields_ = [('real', c_float),
               ('imag', c_float)]

I imagine that I might need another python class that implements an array of structs. Overall I'm just having problems with connecting the pieces together. What needs to be done to eventually call my function in Python basically something like this more or less:

some_ctype_array = SomeConversionCode(cmplx_numpy_array) 
lib.foo(some_ctype_array, length)
like image 594
majorpain1588 Avatar asked Mar 15 '23 03:03

majorpain1588


1 Answers

You can use the ndpointer from numpy.ctypeslib to declare the first argument to be a one-dimensional contiguous array of type numpy.complex64:

import numpy as np
from numpy import ctypeslib

# ...code to load the shared library as `lib` not shown...

# Declare the argument types of lib.foo:
lib.foo.argtypes = [ctypeslib.ndpointer(np.complex64, ndim=1, flags='C'), c_int]

Then you can do, for example,

z = np.array([1+2j, -3+4j, 5.0j], dtype=np.complex64)
lib.foo(z, z.size)

You might want to wrap that in a function that doesn't require the second argument:

def foo(z):
    # Ensure that we use a contiguous array of complex64.  If the
    # call to foo(z, z.size) modifies z in place, and that is the
    # intended effect of the function, then the following line should
    # be removed. (The input z is then *required* to be a contiguous 
    # array of np.complex64.) 
    z = np.ascontiguousarray(z, dtype=np.complex64)
    # Call the C function.
    lib.foo(z, z.size)
like image 145
Warren Weckesser Avatar answered Apr 06 '23 05:04

Warren Weckesser