Magellan88
Magellan88

Reputation: 2573

How to use a filepointer in a struct in cython

I'm trying to use c library in cython that implements a special kind of file struct:

struct XDRFILE
{
    FILE *   fp;       //< pointer to standard C library file handle
    void *   xdr;      //< pointer to corresponding XDR handle
    char     mode;     //< r=read, w=write, a=append
    int *    buf1;     //< Buffer for internal use
    int      buf1size; //< Current allocated length of buf1
    int *    buf2;     //< Buffer for internal use
    int      buf2size; //< Current allocated length of buf2
};

together with methods to open and close such an object:

XDRFILE* xdrfile_open(const char* path, const char* mode)
int xdrfile_close(XDRFILE* xfp)

Now I would like to be able to access the file pointer in this struct and pass it on to fseek and ftell to manipulate the position of the file pointer.

what I've done so far is a cython file with

from cython.view cimport array as cvarray
import numpy as np
cimport numpy as np
from libc.stdio cimport FILE, fseek
cdef extern from "xdrfile.h":
    ctypedef struct XDRFILE:
        FILE*   fp       #< pointer to standard C library file handle
        void*   xdr      #< pointer to corresponding XDR handle       
        char    mode     #< r=read, w=write, a=append                 
        int*    buf1     #< Buffer for internal use                   
        int     buf1size #< Current allocated length of buf1              
        int*    buf2     #< Buffer for internal use                   
        int     buf2size #< Current allocated length of buf2

    XDRFILE* xdrfile_open(const char* path, const char* mode)
    int xdrfile_close(XDRFILE* xfp)
    int xdrfile_read_int(int* ptr, int ndata, XDRFILE* xfp)

def Read( filepath ):
    cdef XDRFILE* FH = xdrfile_open(filepath, "r")
    cdef np.ndarray[np.int32_t, ndim=1] Header = np.zeros( 23, dtype=np.int32 )

    xdrfile_read_int( <int*> Header.data, 23, FH)
    print Header ## up to here everything works just fine

    #now here starts the problem:
    fseek( FH[0].fp, 159240, 0)  
    fseek( FH.fp   , 159240, 0)
    # does not work: "dereferencing pointer of incomplete type"

    ## even more brutal things do not work:
    FH.fp[0] += 159240

What am I missing here? is the declaration in the beginning false or is it the way I pass the pointer?


Ok, thanks for the suggestion I'v tired to read up on how cython handels typedefs and found in the Cython documentation a couple of fomulars how it should work. However I'm still unable to get it right:

I did not think it would matter earlier but this is the exact structure: there is

xdrlib.c:

struct XDRFILE
{
    FILE *   fp;       //< pointer to standard C library file handle
    void *   xdr;      //< pointer to corresponding XDR handle
    char     mode;     //< r=read, w=write, a=append
    int *    buf1;     //< Buffer for internal use
    int      buf1size; //< Current allocated length of buf1
    int *    buf2;     //< Buffer for internal use
    int      buf2size; //< Current allocated length of buf2
};

xdrlib.h:

typedef struct XDRFILE XDRFILE;
XDRFILE* xdrfile_open(const char* path, const char* mode)
int xdrfile_close(XDRFILE* xfp)

and now I would like to warp that with Cython so that I can do:

cdef XDRFILE* FH = xdrfile_open(filepath, "r")
fseek(FH.fp, 1000, 0)

It seems to me that this would be the last case described in the link I posted earlier, so the struct and the typedef have the same name. This suggests no ctypedef insetad a "normal" "cdef struct": with the explanation:

"If the header uses the same name for the tag and typedef, you won’t be able to include a ctypedef for it – but then, it’s not necessary"

However this will give me: "wrong usage of undefined type »struct XDRFILE« " and additionally: "dereferencing of a pointer to incomplete type"

Upvotes: 2

Views: 586

Answers (1)

Fred Foo
Fred Foo

Reputation: 363817

The last line will never work. You cannot indirect a FILE*, let alone add a long to it.

The next error is in the header file. It declares a struct XDRFILE but doesn't typedef that to XDRFILE, then uses XDRFILE without the struct in the function prototypes. When that's fixed, Cython 0.19.2 compiles this without problems.

Upvotes: 1

Related Questions