0

to combine two independent C-written modules, i have to store a function pointer in a double array (pass it to the module), and convert it back later. I tried to stick to https://stackoverflow.com/a/35824907/4859499 However, i can't figure it out in 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 !

Thank You!

Community
  • 1
  • 1
mneuner
  • 433
  • 5
  • 25

1 Answers1

0

Converting a function pointer to any other pointer type is undefined behaviour in C so not guaranteed to work (see last point of the linked answer). In practice function pointer to void* is often OK. There is no good reason to store it as a pointer to a number though.

Looking at your code:

cdef void* ptr = getTestPtr() # getting the function pointer
cdef TEST mytest = <TEST> ptr # testing the function pointer
mytest()                      # still works here

You convert a function pointer to a void pointer and back to a function pointer. Probably OK, but not guaranteed.

cdef double** dPptr = <double**> ptr

Convert the function pointer to a pointer to a pointer to a double. Dodgy.

cdef double* dPtr = dPptr[0]

You de-reference the pointer. This gets you what is in the bit of memory the function is stored in (i.e. executable code). You pretend to interpret that executable code as a pointer to a double.

doubleArrayStorage[0] = dPtr[0] #storing in a given double array at index 0

dPtr[0] looks up an arbitrary bit of memory that it picks by misinterpreting some executable code as a pointer to a double. I'm surprised it doesn't segmentation fault here. Having got the contents of an arbitrary bit of memory you store it in the address pointed to by doubleArrayStorage (which you haven't told us about).

################################################

# starting of back conversion:
cdef double* dPtr2 = &doubleArrayStorage[0]

&doubleArrayStorage[0] reads from then takes the address of doubleArrayStorage. It's equivalent to just writing doubleArrayStorage. You save that as a double pointer. This is just the location of doubleArrayStorage (i.e. correctly a double pointer, but nothing to do with your original function).

cdef void** Pptr2 = <void**> dPtr2

You reinterpret the address of doubleArrayStorage as a pointer to a pointer to a void.

cdef void* ptr2 =  Pptr2[0]

You dereference that address. ptr2 contains whatever is in the first element of doubleArrayStorage which you are pretending is a void*. In reality it's the contents of an arbitrary bit of memory you read earlier.

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

You use the contents of that arbitrary bit of memory as a function pointer and try to execute it.


In summary, I don't believe there's any way to do what you're trying to do safely in C (which means Cython can't do it either).

Community
  • 1
  • 1
DavidW
  • 29,336
  • 6
  • 55
  • 86