When a LispWorks application is delivered as a dynamic library and is loaded by Java, the Java interface must be initialized at some point to make it possible to use it for interfacing with Java. Lisp code which does not interact with Java will work without initializing Java. This includes the initialization function (the first argument to deliver), which can do any required Lisp initialization. However, calls to Java and accepting calls from Java require initialization of the Java interface.
The function setup-deliver-dynamic-library-for-java is used to set this up. In the simple case, you just call setup-deliver-dynamic-library-for-java without any arguments, and then call deliver. When the resulting delivered Lisp image is loaded into Java, Lisp is initialized as usual, and then init-java-interface is automatically called with the host's Java virtual machine.
setup-deliver-dynamic-library-for-java forces the delivered image to be saved as a dynamic library, which when loaded by Java (normally by System.loadLibrary
or System.load
) receives the host's Java virtual machine, initializes the Java interface (unless init-java is passed as nil
) and then calls its function argument if it is non-nil.
The deliver startup function (the first argument to deliver) is called before Java is initialized, so any code that needs to run before initializing the Java interface should be in this function.
By default the initialization is done synchronously, that is by the time that the Java method that loads the LispWorks delivered library returns, LispWorks has finished initializing and is ready to receive calls from Java and other foreign calls. As a result, the loading code on the Java side will hang until the initialization finishes. setup-deliver-dynamic-library-for-java can be told to make initialization asynchronous, that is the loading method just starts the initialization and returns immediately. Calls from Java into Lisp that occur before Lisp is ready will wait until Lisp is ready, and you can check if Lisp is ready by using the Java method com.lispworks.LispCalls.waitForInitialization.
setup-deliver-dynamic-library-for-java works by internally defining a foreign-callable for JNI_OnLoad
and exporting it. You must not define this yourself when using setup-deliver-dynamic-library-for-java.
If you have your own C code that uses the JNI, you can pass the JVM to Lisp yourself via a foreign-callable (or return it from a lisp-to-foreign call), and call init-java-interface with it. In this case, you must not use setup-deliver-dynamic-library-for-java.
The function get-host-java-virtual-machine can be used to get the Java virtual machine that was passed from Java to the internally defined JNI_OnLoad
, and can be used as a predicate to test if JNI_OnLoad
was called. Thus you can create a dynamic library that may be loaded by Java or by a conventional mechanism, and use get-host-java-virtual-machine to distinguish between these two situations.
There is a minimal example of delivering LispWorks for Java in:
(example-edit-file "java/lisp-as-dll/README.txt")
LispWorks User Guide and Reference Manual - 20 Sep 2017