在多个模块中使用函数类型时出现错误签名
我有以下的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))
我觉得这可能是个bug,但也许我在这里漏掉了什么重要的东西……
注意:如果我把所有内容都放在main.pyx
里,而不是使用多个模块,它就能正常工作。
2 个回答
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)
2
这确实看起来像是一个错误,因为系统在尝试合并 filename.pxd
和 filename.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
然后你可以把这个共享的类型定义导入到 integrate.pxd
和 integrate.pyx
中,这样就能确保这两个地方的类型是一样的。