The integrated cross-platform development tool for ANSI Common Lisp LispWorks logo

Lisp Knowledgebase



Title: How do you pass a pointer to a Lisp function to a calling program?

ID: 17002


Product: LispWorks
Version: 4.1
OS: All

Description:
Define the function using FLI:DEFINE-FOREIGN-CALLABLE and call
FLI:MAKE-POINTER with the :SYMBOL-NAME keyword to create a foreign
pointer.

Use a foreign variable to hold the address of the foreign callable. On Win32 platforms, take care to get the calling convention correct (:cdecl or :stdcall ). There's an example for Linux below.

This example was built as a DLL on MS Visual C++

---------------- win32-fcexample.c --------------------------------

int(*FuncPtr1)(int, int) ;
int (*FuncPtr)() ;


void __declspec(dllexport) test (void)
{
  (*FuncPtr)() ;
  (*FuncPtr1) ( (*FuncPtr1)(3,4), 87) ;
}


void __declspec(dllexport) initmyapplication (int (*funca)(int,int), int(*funcb) ())
{
  FuncPtr = funcb ;
  FuncPtr1 = funca ;
}

---------------- win32-fcexample.c --------------------------------

---------------- win32-fcexample.lisp -----------------------------

;; Load time
(fli:define-foreign-function (test "test")
    ()
  :result-type :int
  :module :my-dll
  :calling-convention :cdecl)


(fli:define-foreign-callable
 ("lispval" :result-type :int :calling-convention :cdecl)
 ()
 (format t "One call~%")
 97)


(fli:define-foreign-callable
 ("another" :result-type :int :calling-convention :cdecl)
 ((x :int) (y :int))
 (format t "Another call ~a , ~a~%" x y)
  (* x x y))


(fli:define-foreign-function (init-my-application "initmyapplication")
    ((x :ptr) (y :ptr))
      :module :my-dll)



;; Initialization
(defun init()
 (fli:register-module :my-dll

                  :real-name C:\\fcexample\\Debug\\fcexample.dll")
 (init-my-application (fli:make-pointer :symbol-name "another")

                      (fli:make-pointer :symbol-name "lispval")))

;; Runtime
(defun do-test () (init) (test))

---------------- win32-fcexample.lisp -----------------------------



This example is for Linux, built by
 gcc -shared -o  fcexample.so linux-fcexample.c

-------------linux-fcexample.c ------------------------------------
int(*FuncPtr1)(int, int) ;
int (*FuncPtr)() ;


void test (void)
{
  (*FuncPtr)() ;
  (*FuncPtr1) ( (*FuncPtr1)(3,4), 87) ;
}


void initmyapplication (int (*funca)(int,int), int(*funcb) ())
{
  FuncPtr = funcb ;
  FuncPtr1 = funca ;
}

-------------linux-fcexample.c ------------------------------------

-------------linux-fcexample.lisp----------------------------------
;; Load time
(fli:define-foreign-function (test "test")
    ()
  :result-type :int
  :module :my-dll
  :calling-convention :cdecl)


(fli:define-foreign-callable
 ("lispval" :result-type :int)
 ()
 (format t "One call~%")
 97)


(fli:define-foreign-callable
 ("another" :result-type :int)
 ((x :int) (y :int))
 (format t "Another call ~a , ~a~%" x y)
  (* x x y))


(fli:define-foreign-function (init-my-application "initmyapplication")
    ((x :ptr) (y :ptr))
      :module :my-dll)



;; Initialization
(defun init()
 (fli:register-module :my-dll :real-name "/tmp/fcexample.so")
 (init-my-application (fli:make-pointer :symbol-name "another")

                      (fli:make-pointer :symbol-name "lispval")))

;; Runtime
(defun do-test () (init) (test))

-------------linux-fcexample.lisp----------------------------------

See Also:
Workaround:
Patch:

Hardware:N/A
Summary:
Bug#:
Patch Enhancement#:
Reported:

Top | Back