ctypes: Setting callback functions in C libraries

sjdevnull at yahoo.com sjdevnull at yahoo.com
Mon Jan 29 18:07:14 EST 2007


I realized my wrapping was broken, fixing that below...

On Jan 25, 12:47 am, "sjdevn... at yahoo.com" <sjdevn... at yahoo.com> 
wrote:
> I'm trying to wrap GNU readline withctypes(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:
[SNIP]
> 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.
>
> Usingctypes.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 inctypes' 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 thatctypeswrappers 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 idea?
>
> Thanks very much for your time!

# 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




More information about the Python-list mailing list