在another.pyx
,我有
cdef double myadd(double a, double b):
cdef double c = a + b
return c
在another.pxd
,我有
cdef double myadd(double a, double b)
如果我这样做:
from another cimport myadd
from libc.math cimport exp
from libc.stdio cimport sprintf
def test():
cdef char s[80]
sprintf(s, "%p", <void *> myadd)
print s
sprintf(s, "%p", <void *> &myadd)
print s
sprintf(s, "%p", <void *> exp)
print s
sprintf(s, "%p", <void *> &exp)
print s
0x7f5ccc638130
0x7f5ccc62d5e0
0x32b9622f90
0x32b9622f90
为什么myadd
和&myadd
有所不同?事实证明,如果我使用&myadd
版本并将其分配给函数指针,如果我用参数调用函数指针,程序将在没有警告的情况下崩溃。
答案 0 :(得分:2)
如果你看一下Cython创建的.c,你会看到它声明的是:
/* Module declarations from 'another' */
static double (*__pyx_f_7another_myadd)(double, double); /*proto*/
然后打印(中间省略了很多):
sprintf(__pyx_v_s, __pyx_k_p, ((void *)__pyx_f_7another_myadd));
sprintf(__pyx_v_s, __pyx_k_p, ((void *)(&__pyx_f_7another_myadd)));
__pyx_f_7another_myadd
是指向函数的指针。如果您指向某个特定功能,它将在__pyx_f_7another_myadd
中包含它的地址,但__pyx_f_7another_myadd
本身的地址(即&__pyx_f_7another_myadd
保持不变)。因为函数声明本身就是指向函数的指针,所以可能是一个简单的C ++示例,可以看出它发生了什么:
#include <iostream>
int funcion(int a, int b)
{
std::cout << a+b << std::endl;
}
int (*func) (int,int);
int main()
{
std::cout << (void*) funcion << std::endl;
std::cout << (void*) &funcion << std::endl;
func = funcion;
std::cout << (void*) func << std::endl;
std::cout << (void*) &func << std::endl;
}
0x400886
0x400886
0x400886
0x601198
这里funcion
被声明为函数本身,所以它是它自己的指针(因此两个相等的初始地址)。另一方面,func
是一个函数指针:它存储funcion
地址(第三行),但它有一个自己的地址(因此不同的第四行)。
像(&func) (1,2)
这样的东西不会被编译,因为这个表达式不是函数调用,但(func) (1,2)
是,并且有效。