【问题标题】:Cython: Conversion of a void* to a double and back-conversionCython:将 void* 转换为双重和反向转换
【发布时间】:2017-01-07 14:55:51
【问题描述】:

要组合两个独立的 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 !

谢谢!

【问题讨论】:

    标签: c pointers cython


    【解决方案1】:

    将函数指针转换为任何其他指针类型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]
    

    您取消引用指针。这可以让您了解函数存储在内存中的内容(即可执行代码)。您假装将该可执行代码解释为指向双精度数的指针。

    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]
    

    &amp;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 也做不到)。

    【讨论】:

      猜你喜欢
      • 2012-09-23
      • 2013-06-05
      • 2022-01-17
      • 2015-12-20
      • 2021-07-22
      • 1970-01-01
      • 1970-01-01
      • 2020-10-24
      • 1970-01-01
      相关资源
      最近更新 更多