Calling function retrieved via ctypes

173 views
Skip to first unread message

Richard O

unread,
Jun 18, 2016, 2:08:58 AM6/18/16
to cython-users
Hello,

I am attempting to call, in Cython, a function retrieved from an external shared library via ctypes. The reason is that 'sharelib.so' and 'add' are not determined until runtime. First I verify that everything works with ctypes:
from ctypes import CDLL, c_double, CFUNCTYPE
sharelib
= CDLL('/path/to/sharelib.so')
prototype
= CFUNCTYPE(c_double, c_double, c_double)
sharefunc
= prototype(('add', sharelib))
print(sharefunc(6, 10)) # 16.0

Now I want to call sharefunc from inside a cdef function. My thought was to take advantage of ctypes' addressof() function to get a raw address as an integer in Python, and then cast it to a function pointer on the C side. Here is as far as I've gotten:

from ctypes import CDLL, c_double, addressof, CFUNCTYPE
sharelib
= CDLL('/path/to/sharelib.so')
prototype
= CFUNCTYPE(c_double, c_double, c_double)
sharefunc
= prototype(('add', sharelib))
ctypedef
double (*addfunc)(double x, double y)
cdef
double doubler(double a, double b, unsigned long func):
   
return 2.0 * (<addfunc>func)(a, b)
print(doubler(6, 10, addressof(sharefunc))) # segfault

I am pretty new to Cython so I'm not sure what I'm doing wrong. My sharelib.c looks like this:
double add(double, double);
 
double add(double a, double b) {
   
return a + b;
}
The compile directive was "gcc -shared -o sharelib.so -fPIC sharelib.c"

Richard O

unread,
Jun 18, 2016, 10:41:53 AM6/18/16
to cython-users
Per StackOverflow ( http://stackoverflow.com/questions/32234970/how-to-get-the-pointer-address-of-a-ctypes-c-char-p-instance ), this seems to work okay:

from ctypes import CDLL, cast,  c_double, c_void_p, addressof, CFUNCTYPE
sharelib
= CDLL('/path/to/sharelib.so')

prototype
= CFUNCTYPE(c_double, c_double, c_double)
sharefunc
= prototype(('add', sharelib))

cdef
long funcptr = cast(sharefunc, c_void_p).value
ctypedef
double (*addfunc)(double x, double y)
cdef
double doubler(double a, double b, long func):

   
return 2.0 * (<addfunc>func)(a, b)
print(doubler(6, 10, funcptr))

Reply all
Reply to author
Forward
0 new messages