[cffi-devel] How to pass foreign pointer to c function

fungsin fungsin.lui at gmail.com
Fri Nov 30 20:14:10 UTC 2007


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




More information about the cffi-devel mailing list