문제

I have the following Cython modules:

compmech    
    integrate
        integratev.pxd
        integratev.pyx
    conecyl
        main.pyx

In integratev.pxd I've declared:

ctypedef void (*f_type)(int npts, double *xs, double *ts, double *out,
                    double *alphas, double *betas, void *args) nogil

cdef int trapz2d(f_type f, int fdim, np.ndarray[cDOUBLE, ndim=1] final_out,
                 double xmin, double xmax, int m,
                 double ymin, double ymax, int n,
                 void *args, int num_cores)

I call trapz2d from main.pyx, and the function passed to trapz2d is declared in main.pyx, e.g:

from compmech.integrate.integratev cimport trapz2d

cdef void cfk0L(int npts, double *xs, double *ts, double *out,
                double *alphas, double *betas, void *args) nogil:
    ...

trapz2d(<f_type>cfk0L, fdim, k0Lv, xa, xb, nx, ta, tb, nt, &args, num_cores)

It compiles just fine, but when I run I get the error:

TypeError: C function compmech.integrate.integratev.trapz2d has wrong signature       
(expected int (__pyx_t_8compmech_9integrate_10integratev_f_type, int, PyArrayObject *,
               double, double, int, double, double, int, void *, int),
 got int (__pyx_t_10integratev_f_type, int, PyArrayObject *,
          double, double, int, double, double, int, void *, int))

It seems like a bug to me, but perhaps I am missing something important here...


Note: it works when I put everything inside main.pyx instead of using multiple modules.

도움이 되었습니까?

해결책

This does indeed seem like a bug where the automatic attempt to merge the types in filename.pxd and filename.pyx fails. Using void* is one workaround, but if you want to avoid casting, you can create a third file _util.pxd that contains the shared definition of the function pointer.

# _util.pxd

ctypedef void (*f_type)(int npts, double *xs, double *ts, double *out,
                        double *alphas, double *betas, void *args) nogil

And then you can import the shared typedef into both integrate.pxd and integrate.pyx which guarantees that the types are the same.

다른 팁

The solution was to pass everything as void * and just cast to <f_type> before the function is actually executed, inside trapz2d(). The final layout of the code is:

ctypedef void (*f_type)(int npts, double *xs, double *ts, double *out,
                    double *alphas, double *betas, void *args) nogil

cdef int trapz2d(void *fin, int fdim, np.ndarray[cDOUBLE, ndim=1] final_out,
                 double xmin, double xmax, int m,
                 double ymin, double ymax, int n,
                 void *args, int num_cores)
    cdef f_type f
    f = <f_type>fin
    ...

and in the other code:

from compmech.integrate.integratev cimport trapz2d

cdef void cfk0L(int npts, double *xs, double *ts, double *out,
                double *alphas, double *betas, void *args) nogil:
    ...

trapz2d(<void *>cfk0L, fdim, k0Lv, xa, xb, nx, ta, tb, nt, &args, num_cores)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top