Cython:将void *转换为double和back-conversion

时间:2017-01-07 14:55:52

标签: c pointers cython

组合两个独立的C语言模块,我必须将一个函数指针存储在一个双数组中(将其传递给模块),然后将其转换回来。 我试着坚持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 !

谢谢!

1 个答案:

答案 0 :(得分:0)

将函数指针转换为任何其他指针类型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的地址重新解释为指向空格指针的指针。

cdef void* ptr2 =  Pptr2[0]

您取消引用该地址。 ptr2包含doubleArrayStorage的第一个元素,您假装的是void*。实际上它是你之前读过的任意内存的内容。

cdef TEST mytest2 = <TEST> ptr2
mytest2()                         #SEGMENTATION FAULT !

您将该任意内存位的内容用作函数指针并尝试执行它。

总之,我不相信有任何方法可以做你在C中安全地做的事情(这意味着Cython也不能这样做)。