3

I am trying to write a Cython wrapper around a C library. I am very new to Cython, so my apologies in advance if the problem is obvious.

In a file wrapper.pxd, I define a struct (reduced example):

cdef extern from "thiscouldbeyourlibrary.h":
    cdef struct foo:
        double **output

I then have a class:

cdef class Bar:
    cdef wrapper.foo __stuff

    cdef do_something(self):
        self.__stuff.output = NULL

This fails:

Cannot convert 'void *' to Python object.

Apparently, Cython cannot be sure that self.__stuff.output is always a pointer. But I declared its type and the class is a "cdef" class, so I don't really understand why.

Saullo G. P. Castro
  • 56,802
  • 26
  • 179
  • 234
  • Note that there are better tools for the specific task of generating *Python wrappers*, like [SWIG](http://www.swig.org/) (that's what `pywin32` uses). – ivan_pozdeev Sep 12 '14 at 16:08
  • @ivan_pozdeev I know. There is actually already a wrapper for the specific library I need, based on SWIG. However, I was having some problems with it (and by "problems" I mean segfaults), and it doesn't do precisely what I want (NumPy interoperability). – EyPandaBear Sep 12 '14 at 16:17
  • Just a guess: use `None` instead of `NULL` - that looks more like a "Python object" :^) – ivan_pozdeev Sep 12 '14 at 23:17
  • @EyPandaBear did you check the answer below? – Saullo G. P. Castro Oct 13 '14 at 08:27

1 Answers1

1

The problem is the incompatibility between NULL and double **. You could assign it to a char, int or void *, for example, doing:

wrapper.pyd:

cdef extern from "thiscouldbeyourlibrary.h":
    cdef struct foo:
        char a
        int b
        void *c
        double **output

thiscouldbeyourlibrary.h:

struct foo
{ 
    char a;
    int b;
    void *c;
    double **output;
};

main.pyx:

cimport wrapper

cdef class Bar:
    cdef wrapper.foo __stuff
    def __init__(self):
        self.__stuff.a = <char>NULL
        self.__stuff.b = <int>NULL
        self.__stuff.c = NULL

def main():
    bar = Bar()
    print bar.__stuff.a
    print bar.__stuff.b

If you had allocated the memory for output before, you could have done it:

self.__stuff.output[0] = NULL

without allocating it will crash...

Saullo G. P. Castro
  • 56,802
  • 26
  • 179
  • 234