I'm having problem figuring out how to pass a foreign static pointer to a c function using cffi.
I use SWIG to generate binding for readline
This is the meta keymap defined in keymap.h
extern KEYMAP_ENTRY_ARRAY emacs_meta_keymap;
which I need to pass as the second argument to
extern int rl_bind_key_in_map PARAMS((int, rl_command_func_t *, Keymap));
In the example below, I can use rl_bind_key without any problem.
(in-package :cl-user)
(cffi:defcallback rl-magic-tab :int ((rep :int) (chord :int)) (rl::rl_insert 1 (char-code #\t)) (rl::rl_insert 1 (char-code #\a) (rl::rl_insert 1 (char-code #\b))))
CL-USER > (rl_initialize)
CL-USER > (rl::rl_bind_key (char-code #\tab) (cffi:callback rl-magic-tab))
However, when I tried to pass rl::emacs_meta_keymap as is or via (cffi:convert- to-foreign rl::emacs_meta_keymap :pointer) as the 2nd argument to rl_bind_key_in_map I get exceptions (both in lispworks and clisp)
CL-USER > (rl::rl_bind_key_in_map (char-code #,) (cffi:callback rl-magic-tab) (cffi:convert-to-foreign rl::emacs_meta_keymap :pointer))
Error: Signal B [code 0] at B7FA6C90 {inside foreign code} eax 0 ; ebx B7FBB42C ; ecx 160 ; edx B7FBB9D4 esp BFADA9A4 ; ebp BFADA9AC ; esi 2004DC82 ; edi B7FBBDE0 1 (abort) Return to level 0. 2 Restart top-level loop.
CL-USER > (rl::rl_bind_key_in_map (char-code #,) (cffi:callback rl-magic-tab) rl::emacs_meta_keymap)
Error: Signal B [code 0] at B7FA6C90 {inside foreign code} eax 0 ; ebx B7FBB42C ; ecx 160 ; edx B7FBB9D4 esp BFADA8F4 ; ebp BFADA8FC ; esi 2004DC82 ; edi 0 1 (abort) Return to level 0. 2 Restart top-level loop.
If I wrap readline's rl_bind_key_in_map with a c function, then I can call it but it's cumbersome.
#include <readline/keymaps.h> #include <readline/readline.h>
extern int rl_bind_meta_key (int key, rl_command_func_t *func) { return rl_bind_key_in_map (key, func, emacs_meta_keymap); }
(cffi:defcfun ("rl_bind_meta_key" rl_bind_meta_key) :int (arg0 :int) (arg1 :pointer))
CL-USER > (rl_bind_meta_key (char-code #,) (cffi:callback rl-magic-tab))
Below is a portion of the cffi readline binding
;;SWIG example (in-package :rl)
(cffi:defcfun ("rl_initialize" rl_initialize) :int)
(cffi:defcfun ("readline" readline) :string (arg0 :string))
(cffi:defcfun ("rl_insert" rl_insert) :int (arg0 :int) (arg1 :int))
;; extern int rl_bind_key PARAMS((int, rl_command_func_t *));
(cffi:defcfun ("rl_bind_key" rl_bind_key) :int (arg0 :int) (arg1 :pointer))
;; extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, emacs_meta_keymap, emacs_ctlx_keymap;
(cffi:defcvar ("emacs_meta_keymap" emacs_meta_keymap) :pointer)
;; extern int rl_bind_key_in_map PARAMS((int, rl_command_func_t *, Keymap));
(cffi:defcfun ("rl_bind_key_in_map" rl_bind_key_in_map) :int (arg0 :int) (arg1 :pointer) (arg2 :pointer))
Thanks fungsin
On 30/11/2007, fungsin fungsin.lui@gmail.com wrote:
return rl_bind_key_in_map (key, func, emacs_meta_keymap);
AFAICT, emacs_meta_keymap is an array. My C-fu is getting weak but I think that in this particular case emacs_meta_keymap (or &emacs_meta_keymap[0]) == &emacs_meta_keymap.
(cffi:defcvar ("emacs_meta_keymap" emacs_meta_keymap) :pointer)
So, given that definition, the equivalent of &emacs_meta_keymap is (get-var-pointer 'emacs_meta_keymap). Alternatively, you can use (foreign-symbol-pointer "emacs_meta_keymap").