ctypes: Setting callback functions in C libraries

sjdevnull at yahoo.com sjdevnull at yahoo.com
Thu Jan 25 00:47:27 EST 2007


Hey,

I'm trying to wrap GNU readline with ctypes (the Python readline
library doesn't support the callback interface), but I can't figure out
how to set values to a variable inside the library.  This is Python 2.5
on Linux.  Here's what I have so far--if you comment out the memmove
call (3 lines) it works as expected:

# START
#!/usr/local/bin/python2.5
import ctypes

ctypes.cdll.LoadLibrary("libcurses.so")#, mode=ctypes.RTLD_GLOBAL)
ctypes.CDLL("libcurses.so", mode=ctypes.RTLD_GLOBAL)
ctypes.cdll.LoadLibrary("libreadline.so")
readline = ctypes.CDLL("libreadline.so")

RL_COMPLETION_FUNC_T =
ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_char_p),
        ctypes.c_char_p, ctypes.c_int, ctypes.c_int)
RL_LINE_BUFFER = ctypes.c_char_p.in_dll(readline, "rl_line_buffer")
RL_ATTEMPTED_COMPLETION_FUNCTION =
RL_COMPLETION_FUNC_T.in_dll(readline,

"rl_attempted_completion_function")

def our_complete(text, start, end):
    print "Test", text, start, end
    rv = None
    arrtype = ctypes.c_char_p*4
    globals()["rv"] = arrtype("hello", "hatpin", "hammer", None)
    globals()["crv"]=ctypes.cast(rv, ctypes.POINTER(ctypes.c_char_p))
    return rv
ourfunc = RL_COMPLETION_FUNC_T(our_complete)

_readline = readline.readline
_readline.argtypes = [ctypes.c_char_p]
_readline.restype = ctypes.c_char_p

ctypes.memmove(ctypes.addressof(RL_ATTEMPTED_COMPLETION_FUNCTION),
               ctypes.addressof(ourfunc),
               4)
line = _readline("Input: ")
print "INPUT was: ", line
#END

I need to assign ourfunc to RL_ATTEMPTED_COMPLETION_FUNCTION, but
obviously simple assignment rebinds the name rather than assigning it
to the C variable.

Using ctypes.memmove to overwrite it(as I have here) will run the
function but segfault when ourfunc goes to return (poking around with
the debugger shows it's dying in ctypes' callbacks.c at line 216, "keep
= setfunc(mem, result, 0);" because setfunc is NULL).  I'm not entirely
sure that's not because of some error in the prototyping or restype
setting rather than as a result of memmove, but the memmove seems
sketchy enough (only sets the function pointer itself presumably, not
anything that ctypes wrappers need) that I'm looking for a better way
to do it.

As it is, returning rv directly or simply returning None causes the
same segfault.


Any ideas?

Thanks very much for your time!




More information about the Python-list mailing list