typedef struct consistency between C and Cython

742 views
Skip to first unread message

Al Danial

unread,
Nov 11, 2012, 11:30:03 PM11/11/12
to cython-users
I'm trying to wrap a legacy C library with cython.  The C library
defines a custom data type with a 'typedef struct'.  The Python 
side of the code needs to initialize C variables having this
type but I haven't figured out how to declare the variables
correctly.  Cython complains that

  ./library.c:2:6: note: expected ‘legacy_struct’ but argument is of type ‘__pyx_t_10new_module_legacy_struct’

Platform:
  Python 2.7.3
  Cython 0.17.1
  Fedora 17 i686

Files that boil the problem down to the bare minimum are below and 
also in the attached tar file.  Anyone know where I'm going wrong?
      -- Al

-------------- \/ cyth.pyx
#!/usr/bin/python

ctypedef struct legacy_struct:
    int     *S_start
    double  *N      
    char    *data   

cdef extern from "library.c":
    int  legacy_function(int          nC ,
                        legacy_struct A)
import  numpy as np
cimport numpy as np
np.import_array()

def Save():
    cdef int nC = 0
    cdef legacy_struct m
    legacy_function( nC , <legacy_struct> m)
    return
-------------- /\ cyth.pyx

-------------- \/ header.h
typedef struct {
    int     *S_start  ;
    double  *N        ;
    char    *data     ;
} legacy_struct;

int legacy_function(int           nC ,
                    legacy_struct A  );
-------------- /\ header.h

-------------- \/ library.c
#include "header.h"
int  legacy_function(int           nC,
                    legacy_struct  A ) {
    A.S_start[nC] = 0;
    return 1;
-------------- /\ library.c

-------------- \/ Makefile
CFLAGS= -g
LDFLAGS= -g

all: cyth.pyx library.c header.h
LDFLAGS=$(LDFLAGS) CFLAGS=$(CFLAGS) python setup.py build_ext --inplace

clean:
rm -rf build *.so cyth.c library.o
-------------- /\ Makefile

-------------- \/ setup.py
import numpy
from Cython.Distutils import build_ext

def configuration(parent_package='', top_path=None):
    from numpy.distutils.misc_util import Configuration
    config = Configuration('', parent_package, top_path)
    config.add_extension('new_module',
                         sources=['cyth.pyx'],
                         depends=['cyth.c'],
                         extra_compile_args=["-g"],
                         extra_link_args=["-g"],
                         include_dirs=[numpy.get_include()])
    return config

if __name__ == '__main__':
    params = configuration(top_path='').todict()
    params['cmdclass'] = dict(build_ext=build_ext)
    from numpy.distutils.core import setup
    setup(**params)
-------------- /\ setup.py

cython_C_struct.tar.gz

Stefan Behnel

unread,
Nov 12, 2012, 1:20:34 AM11/12/12
to cython...@googlegroups.com
Al Danial, 12.11.2012 05:30:
> I'm trying to wrap a legacy C library with cython. The C library
> defines a custom data type with a 'typedef struct'. The Python
> side of the code needs to initialize C variables having this
> type but I haven't figured out how to declare the variables
> correctly. Cython complains that
>
> ./library.c:2:6: note: expected ‘legacy_struct’ but argument is of type
> ‘__pyx_t_10new_module_legacy_struct’

It's the C compiler complaining here.


> Files that boil the problem down to the bare minimum are below and
> also in the attached tar file. Anyone know where I'm going wrong?
> -- Al
>
> -------------- \/ cyth.pyx
> #!/usr/bin/python
>
> ctypedef struct legacy_struct:
> int *S_start
> double *N
> char *data
>
> cdef extern from "library.c":
> int legacy_function(int nC ,
> legacy_struct A)

Since you're dealing with an externally defined type, you have to move the
ctypedef into the cdef extern block. Otherwise, Cython will define the type
itself in the C code, which is not what you want here.

Stefan

Al Danial

unread,
Nov 12, 2012, 10:15:11 AM11/12/12
to cython-users
So simple!  And yet I'd have never figured it out on my own.  Thanks,
my code builds cleanly now. 
Reply all
Reply to author
Forward
0 new messages