bloub
bloub

Reputation: 610

How to get a C object and pass it in argument of a function in cython

I am trying to use a C library "myClib" from python.

This library has a function "myCfunction" that return a pointer struct "myCStruct" and then had other functions that take a pointer of this struct in argument.

I don't have the definition of this struct I only get this in the .h file :

typedef struct myCStruct myCStruct

The library is provided with as a static library with a .a file. Some .so files are also provided they contains some dependencies used by the library. The .h files are also provided but the full definition of "myCStruct" seems not provided in any of the .h.

I don't have to read or process any information that would be contained in this object but I need to pass it in argument of an other C functions of the library.

Right now to execute the C code I am using cython to generate a .so file that I can import in my python code.

The definition of the function in my pyx file looks like this :

cdef extern from "myClib.h":
  void myCfunction()

def py_myCfunction():
  return myCfunction()

I didn't declare the return type of py_myCfunction as I didn't define any class matching the myCStruct since I don't have any idea about the members.

My problem is that when I call py_myCfunction in my python program I am getting an object of type NoneType.

So 2 questions :

Upvotes: 0

Views: 116

Answers (1)

dirck
dirck

Reputation: 868

  • You need to declare the C API so cython knows what it is and how to call it

  • You should wrap the C struct * in a Python class, and add methods to the class that call the other C API functions that reference the struct

Here's example cython code based on your question:


# declare external stuff for cython

cdef extern from "myClib.h":

    struct myCStruct:
        pass

    struct myCStruct *myCFunction();
    int otherFunction(struct myCStruct *cstruct, int parameter);

# define python glue for python

cdef class MyPythonClass:
    cdef myCStruct *cstruct

    def __cinit__(self):
        self.cstruct = myCFunction()
    
    # plus methods that call other functions in myClib using the self.cstruct
    def other(self, parameter):
        return otherFunction(self.cstruct, parameter)

    # if myCLib has "myCStruct_Free"
    def __dealloc__(self):        
        if self.cstruct != NULL:
            myCStruct_Free(self.cstruct)
            self.cstruct = NULL

Upvotes: 2

Related Questions