wl2776
wl2776

Reputation: 4327

Map array of C structs in struct to Cython

UPDATE Minimal example on GitHub: https://github.com/wl2776/cython_error

I've got a C library, that I want to access from Python. I'm developing a Cython wrappers for it.

The library has following declarations:

file "globals.h"

typedef struct
{
    int x;
    int y;
    int radius;
} circleData;

file "O_Recognition.h"

#include "globals.h"
typedef struct 
{
   int obj_count;
   circleData circle_data[2];
   float parameters[2];
} objectData;

I'm mapping these types to Cython in .pxd file, as follows:

file "cO_Recognition.pxd":

cdef extern from "globals.h":
    ctypedef struct circleData:
        int x;
        int y;
        int radius;

cdef extern from "O_Recognition.h":
    ctypedef struct objectData:
        int obj_count;
        circleData circle_data[2];
        float parameters[2];

And this does not compile. I am getting errors:

Error compiling Cython file:
------------------------------------------------------------
...
    void PyTuple_SET_ITEM(object  p, Py_ssize_t pos, object o)
    void PyList_SET_ITEM(object  p, Py_ssize_t pos, object o)

@cname("__Pyx_carray_to_py_circleData")
cdef inline list __Pyx_carray_to_py_circleData(circleData *v, Py_ssize_t length):
                                                ^
------------------------------------------------------------
carray.to_py:112:45 'circleData' is not a type identifier

One more detail, this is a part of the CMake project, that is built using this example from GitHub: https://github.com/thewtex/cython-cmake-example

Relevant part of CMakeLists.txt includes .pyx file with other name, that cimports this cDeclarations.pxd

Upvotes: 1

Views: 1155

Answers (1)

danny
danny

Reputation: 5270

The issue is that circleData is undefined in the O_Recognition.h extern block. Its previous definition only applies to the globals.h extern block.

Just need to include its type so that Cython knows what it is. It does not need to be re-defined.

cdef extern from "globals.h" nogil:
    ctypedef struct circleData:
        int x;
        int y;
        int radius;

cdef extern from "O_Recognition.h" nogil:
    ctypedef struct circleData:
        pass
    ctypedef struct objectData:
        int obj_count;
        circleData circle_data[2];
        float parameters[2];

When the code is compiled, the .c file will include both header files and get the type definition for circleData from globals.h.

Technically, the definition of circleData members in globals.h extern block is not needed either unless the structure members are going to be used in Cython code.

Remember, pxd files are definitions of Cython code, not C code. Only include members that are to be used in Cython code, otherwise can just define the type sans members per circleData per recognition extern block above.

Upvotes: 2

Related Questions