I use Raspberry Pi to interact with custom hardware connected to GPIO. The management software is written in Python and the custom hardware interface is written in C, as this is a much faster implementation of C. Now I need to start calling my C functions from my Python and have recently learned how to wrap C in Cython. I have everything to work with the exception of passing a Python list to a C function.
My custom hardware should be sent from 1 to 32 bytes, hence the use of an array.
Cython tutorials and other links that I read on the Internet are really simple and do not include how to pass lists to C, use numpy which I don't use, or use very complex code examples that don't have enough documentation for me to understand it is right.
Now I have:
test.c
#include <stdio.h>
#include "test.h"
void pop(void) {
a[0] = 0x55;
a[1] = 0x66;
a[2] = 0x77;
a[3] = '\0';
}
void putAll(int n, char c[]) {
memcpy(a, c, n);
}
char *getAll(void) {
return &a[0];
}
test.h
char a[4];
void putAll(int n, char[]);
char *getAll(void);
pytest.pyx
cimport defns
def pypop():
defns.pop()
def pyPutAll(int n, char[:] pyc):
cdef char* c = pyc
defns.putAll(n, c)
def pyGetAll():
cdef char* c = defns.getAll()
cdef bytes pyc = c
print pyc
defns.pxd
cdef extern from "test.h":
char a[4]
void pop()
void putAll(int n, char c[])
char *getAll()
Using the tutorials on cython.org , my getAll () and pop () functions work, but when I turn on the putAll () function (taken from the code example process_byte_data found by reference under Unicode and passing strings> Accepting strings from Python code), I get this error:
python setup.py build_ext -i
Error compiling Cython file:
------------------------------------------------------------
...
def pyputAll(int n, char[:] pyc):
^
------------------------------------------------------------
pytest.pyx:13:25: Expected an identifier or literal
Now I have a way around this - concatenate up to 32 bytes into an int and pass as a long int, and then split it into C, but this is very ugly.
, Cython , C, , Python.
.
()
. , , .
pytest.pyx
...
def pyPutAll(int n, c):
cdef int *ptr
ptr = <int *>malloc(n*cython.sizeof(int))
if ptr is NULL:
raise MemoryError()
for i in xrange(n):
ptr[i] = c[i]
defns.putAll(n, ptr)
free(ptr)
...
test.c
void putAll(int n, int c[])
{
char d[n];
int i;
for (i=0;i<n;i++) {
d[i] = c[i];
}
memcpy(addr, d, n);
}
, int python/cython, char C. pyPutAll() pytest.pyc python. C- . , C, , , C.
, , - .
Matt