The CL+SSL system implements the desirable configuration mechanism, where the user can specify the location of .so, .mylib, and .dll files. This is the skeleton model of how another interface library can implement binary library configuration.

External C and C++ libraries are available in .so, .dll, and .mylib file formats. Using CFFI a Common Lisp interface system is written to allow the use of the functions and structures from that foreign library.

The location of the .so, .dll, or .mylib file on the user's computer could be guessed, but as a last resort give the user the ability to specify that location.


In this example mode, I am assuming the term, or token, NEEDED is replaced by the name of the library.

Purpose

You need to offer the user the ability to override how to find the external library, in the case of external library version updates.

What the interface library author should do

There are three parts:

  • the config system definition
  • the config system implementation
  • where your interface code expects to load the library.

Define the config secondary system

  (defsystem cl-NEEDED/config
    (depends-on "CFFI"))

Create the config package implementation

To allow your cl-NEEDED system to be configured a secondary system called cl-NEEDED/config should be similar to this:

  (defpackage :cl-NEEDED/config
    (:use
      :common-lisp
      :cffi)
    (:export
      #:define-libNEEDED-path))

   (in-package :cl-NEEDED/config)
   ;; Define flag to assume we need to use our default search logic.
   (defvar *libNEEDED-override* nil)

   (defmacro define-libNEEDED-path (path)
     `(progn
	;; Set your known path for libNEEDED for cffi
	(cffi:define-foreign-library libNEEDED (t ,path))
	;; Flag to just use the defined path
	(setq *libNEEDED-override* t)))

Where your interface expects to load the library

The override system defines a CFFI library, libNEEDED with a pass with the assumption that a (cffi:load-library libNEEDED). This code assumes that the library location guessing code will result in a call to of (cffi:define-foreign-library libNEEED (t path-you-checked)).

This code shows a macro definition that does that:

  (unless cl-NEEDED/config::*libNEEDED-override*
    ;; Your legacy path-finding code goes here.
    ;; You are trying to find the libNEEDED path for cffi
  )
  (cffi:load-library libNEEDED)

Simple Use Case: a config-NEEDED package.

The most simple example is for a programmer to write her configuration for NEEDED, by adding the correct path in main/preload function. Now as long as her use of NEEDED occurs after config-NEEDED is loaded, NEEDED will use her configuration.

System definition

This is an asd for the system to configure the cl-NEEDED

(defsystem "config-NEEDED"
  :description "supply binding for NEEDED .dl "
  :author "NEEDED@example.com"
  :license "NEEDED LICENSE"
  :depends-on ("cffi" "cl-NEEDED/config")
  :components ((:file "main")))

System implementation

The config-NEEDED/main.lisp is where we call define-NEEDED-lib with the hardcoded path to the correct library file.

   (defpackage #:config-NEEDED/main
    (:use
     #:cl
     #:cl-NEEDED/config)
    (:export
     #:do-configure))

  (in-package #:config-NEEDED/main)

  (defun do-configure ()
    ;; Your will need to change this for your use case.
    (define-NEEDED-lib "c:/my/path/to/NEEDED.dll"))

  (do-configure)

Other Use Case

To Be Done.