要组合两个独立的 C 编写模块,我必须将函数指针存储在 double 组中(将其传递给模块),并稍后将其转换回来。 我试图坚持https://stackoverflow.com/a/35824907/4859499 但是,我无法在 Cython 中弄清楚:
cdef void* ptr = getTestPtr() # getting the function pointer
cdef TEST mytest = <TEST> ptr # testing the function pointer
mytest() # still works here
cdef double** dPptr = <double**> ptr
cdef double* dPtr = dPptr[0]
doubleArrayStorage[0] = dPtr[0] #storing in a given double array at index 0
################################################
# starting of back conversion:
cdef double* dPtr2 = &doubleArrayStorage[0]
cdef void** Pptr2 = <void**> dPtr2
cdef void* ptr2 = Pptr2[0]
cdef TEST mytest2 = <TEST> ptr2
mytest2() #SEGMENTATION FAULT !
谢谢!
最佳答案
将函数指针转换为任何其他指针类型 is undefined behaviour in C所以不能保证有效(请参阅链接答案的最后一点)。实际上,指向 void*
的函数指针通常是可以的。不过,没有充分的理由将其存储为指向数字的指针。
查看您的代码:
cdef void* ptr = getTestPtr() # getting the function pointer
cdef TEST mytest = <TEST> ptr # testing the function pointer
mytest() # still works here
将函数指针转换为 void 指针,然后再转换回函数指针。可能没问题,但不能保证。
cdef double** dPptr = <double**> ptr
将函数指针转换为指向 double 型指针的指针。狡猾的。
cdef double* dPtr = dPptr[0]
您取消引用该指针。这可以让你知道函数存储在内存中的内容(即可执行代码)。您假装将该可执行代码解释为指向 double 型的指针。
doubleArrayStorage[0] = dPtr[0] #storing in a given double array at index 0
dPtr[0]
查找它通过将某些可执行代码误解为指向 double 的指针而选择的任意内存位。我很惊讶这里没有段错误。获取任意内存位的内容后,您将其存储在由 doubleArrayStorage
指向的地址中(您还没有告诉我们)。
################################################
# starting of back conversion:
cdef double* dPtr2 = &doubleArrayStorage[0]
&doubleArrayStorage[0]
读取然后获取 doubleArrayStorage
的地址。它相当于只编写doubleArrayStorage
。您将其保存为双指针。这只是 doubleArrayStorage 的位置(即正确的双指针,但与原始函数无关)。
cdef void** Pptr2 = <void**> dPtr2
您将 doubleArrayStorage
的地址重新解释为指向 void 的指针。
cdef void* ptr2 = Pptr2[0]
您取消引用该地址。 ptr2
包含 doubleArrayStorage
第一个元素中的内容,您假装它是 void*
。实际上,它是您之前读取的任意内存位的内容。
cdef TEST mytest2 = <TEST> ptr2
mytest2() #SEGMENTATION FAULT !
您使用该任意内存位的内容作为函数指针并尝试执行它。
<小时/>总之,我不相信有任何方法可以在 C 中安全地完成您想要做的事情(这意味着 Cython 也无法做到)。
关于Cython:将 void* 转换为 double 和反向转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41522760/