LispWorks Delivery User Guide > 4 Delivering your Application > 4.4 Delivering a dynamic library


4.4.4 Further example

This example builds a dynamic library which in principle could be loaded by any application and called to calculate square numbers.

For illustrative purposes, we show how to load the dynamic library into the LispWorks development image. This illustrates some platform-specific initialization. Then we use the library, ensure it exits cleanly, and finally delete the dynamic library file.

Note that on Linux/Macintosh/FreeBSD, to deliver a dynamic library, the build machine must have a C compiler installed.

For convenience the code is presented without external files. To run it, copy each form in turn and enter it at the Listener prompt.

  1. Define a path for the dynamic library:
  2. (defvar *dynamic-library-path*
      (merge-pathnames (make-pathname :name "CalculateSquareExample"
                                      :type scm::*object-file-suffix*)
  3. Define a function to create the dynamic library:
  4. (defun save-dynamic-library ()
      (let* ((file (make-temp-file t "lisp"))
             (ns (namestring file)))
        (format file
            (fli:define-foreign-callable (calculate-square :result-type :int)
                ((arg :int))
              (* arg arg))
        (deliver nil ~s 5 :dll-exports '(\"calculate_square\"))"
          (namestring *dynamic-library-path*))
        (close file)
        (sys:call-system-showing-output (list (lisp-image-name)
                                             ns ))
        (delete-file file nil)))
  5. Create the dynamic library:
  6. (save-dynamic-library)
  7. Define functions to use the dynamic library:
  8. (fli:define-foreign-function (my-quit-lispworks "QuitLispWorks")
        ((force :int)
         (milli-timeout :int))
      :result-type :int
      ;; specifying :module ensures the foreign function finds
      ;;  the function in our module
      :module 'my-dynamic-library)
    (fli:define-foreign-function (my-init-lispworks "InitLispWorks")
        ((milli-timeout :int)
         (base-address (:pointer-integer :int))
         (reserve-size (:pointer-integer :int)) ; really size_t
      :result-type :int
      :module 'my-dynamic-library)
    (fli:define-foreign-function calculate-square
        ((arg :int))
      :result-type :int
      :module 'my-dynamic-library)
  9. Define a function to load the dynamic library, use it, and then unload it:
  10. (defun run-the-dynamic-library ()
      (fli:register-module 'my-dynamic-library
                           :connection-style :immediate
                           :file-name *dynamic-library-path*)
    ;; Windows and Mac OS X can detect and resolve memory clashes.
      ;; On other platforms, tell the library to load at different
      ;;  address (that is, relocate) because otherwise it will use
      ;;  the same address as the running LispWorks development image.
      ;; Relocation may be needed when loading a LispWorks dynamic 
      ;; library in other applications.
      #-(or mswindows darwin)
      (my-init-lispworks 0
                         #+lispworks-64bit #x5000000000
                         #+lispworks-32bit #x50000000
      (dotimes (x 4)
        (format t "square of ~d = ~d~%" x
                (calculate-square x)))
      (my-quit-lispworks 0 1000)
      (fli:disconnect-module 'my-dynamic-library))
  11. Use the dynamic library:
  12. (run-the-dynamic-library)

    Check the output to see that it computed square numbers.

  13. (optional) Delete the dynamic library file:
(delete-file *dynamic-library-path* nil)
LispWorks Delivery User Guide - 22 Dec 2009