By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,810 Members | 818 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,810 IT Pros & Developers. It's quick & easy.

ctypes: Setting callback functions in C libraries

P: n/a
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_COMPL ETION_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!

Jan 25 '07 #1
Share this Question
Share on Google+
1 Reply


P: n/a
I realized my wrapping was broken, fixing that below...

On Jan 25, 12:47 am, "sjdevn...@yahoo.com" <sjdevn...@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_COMPL ETION_FUNCTION),
ctypes.addressof(ourfunc),
4)
line = _readline("Input: ")
print "INPUT was: ", line
#END

Jan 29 '07 #2

This discussion thread is closed

Replies have been disabled for this discussion.