在多个模块中使用函数类型时出现错误签名问题

3
我有以下Cython模块:
compmech    
    integrate
        integratev.pxd
        integratev.pyx
    conecyl
        main.pyx

integratev.pxd中,我声明了:
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)

我从main.pyx中调用trapz2d,并且传递给trapz2d的函数在main.pyx中声明,例如:

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)

代码编译没有问题,但运行时出现错误:

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))

在我看来,这似乎是一个错误,但也许我在这里漏掉了一些重要的东西...


注意:当我把所有东西放在main.pyx中而不是使用多个模块时,它可以工作。

2个回答

2

这确实看起来像一个错误,自动尝试合并filename.pxdfilename.pyx中的类型失败了。使用void*是一种解决方法,但如果想避免强制转换,可以创建第三个文件_util.pxd,其中包含函数指针的共享定义。

# _util.pxd

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

然后,您可以将共享的typedef导入到integrate.pxdintegrate.pyx中,这可以确保类型相同。


0
解决方案是将所有内容都作为void *传递,并在实际执行函数之前,在trapz2d()内部进行<f_type>的转换。代码的最终布局如下:
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
    ...

而在另一段代码中:

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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接