51

If I have the follow 2 sets of code, how do I glue them together?

void
c_function(void *ptr) {
    int i;

    for (i = 0; i < 10; i++) {
        printf("%p", ptr[i]);
    }

    return;
}


def python_routine(y):
    x = []
    for e in y:
        x.append(e)

How can I call the c_function with a contiguous list of elements in x? I tried to cast x to a c_void_p, but that didn't work.

I also tried to use something like

x = c_void_p * 10 
for e in y:
    x[i] = e

but this gets a syntax error.

The C code clearly wants the address of an array. How do I get this to happen?

No One in Particular
  • 2,586
  • 3
  • 24
  • 32

4 Answers4

94

The following code works on arbitrary lists:

import ctypes
pyarr = [1, 2, 3, 4]
arr = (ctypes.c_int * len(pyarr))(*pyarr)
Delgan
  • 14,714
  • 6
  • 77
  • 119
Gabi Purcaru
  • 28,478
  • 8
  • 71
  • 89
16

This is an explanation of the accepted answer.

ctypes.c_int * len(pyarr) creates an array (sequence) of type c_int of length 4 (python3, python 2). Since c_int is an object whose constructor takes one argument, (ctypes.c_int * len(pyarr)(*pyarr) does a one shot init of each c_int instance from pyarr. An easier to read form is:

pyarr = [1, 2, 3, 4]
seq = ctypes.c_int * len(pyarr)
arr = seq(*pyarr)

Use type function to see the difference between seq and arr.

akhan
  • 2,446
  • 2
  • 16
  • 10
11

From the ctypes tutorial:

>>> IntArray5 = c_int * 5
>>> ia = IntArray5(5, 1, 7, 33, 99)
Ryan Ginstrom
  • 13,275
  • 5
  • 39
  • 59
2
import ctypes
import typing

def foo(aqs : typing.List[int]) -> ctypes.Array:
    array_type = ctypes.c_int64 * len(aqs)
    ans = array_type(*aqs)
    return ans

for el in foo([1,2,3]):
    print(el)

this will give:

1
2
3
Jörg Beyer
  • 3,447
  • 19
  • 35