To use LispWorks in an Android project, the Android project needs three extra files:
This defines the support classes in the Java package com.lispworks
. This file is part of the LispWorks distribution, and can be found in the etc
directory in the LispWorks distribution:
(lispworks-file "etc/lispworks.jar")
You must add this file to your project. On Eclipse, it should be added to the build path, though you can also just copy it to the libs
directory. On Android Studio 0.4.6 with the default configuration you can put it in app/libs
.
2,3) A LispWorks heap and dynamic library. These two files are generated by deliver-to-android-project. Both have the same base name (default "LispWorks"
). The library has "lib"
before the base name and ".so"
after it. The heap file name is the library name with the string ".lwheap"
appended. The heap file needs to be in the "assets"
sub-directory of the project, while the dynamic library needs to be in armeabi-v7a
sub-directory of the jni libs directory of the project. For Eclipse, the jni libs directory is libs
at the top level, and assets
is at the top too, so the files are by default in:
assets/LispWorks.so.lwheap
libs/armeabi-v7a/LispWorks.so
In Android Studio 0.4.6, the jni libs directory is jniLibs
, and both it and the assets
directory are in the "main" directory, so by default the files are in:
app/src/main/assets/LispWorks.so.lwheap
app/src/main/jniLibs/armeabi-v7a/LispWorks.so
By default, deliver-to-android-project puts these files in these places, but note that on Eclipse if you have native libraries the default does not work. See full discussion in the entry for deliver-to-android-project.
The lispworks.jar
file is required so that your Java IDE knows about classes in com.lispworks
, so you need it while working on the Java code that interfaces with Lisp. The other two files are needed only when you actually build the project.
Once these three files are in place, the Android project can be built and installed like any Android project. To use LispWorks, the method com.lispworks.Manager.init must be called to initialize LispWorks. If library-name was passed to deliver-to-android-project, then com.lispworks.Manager.init must be called with a matching name, otherwise the default "LispWorks" is used. com.lispworks.Manager.init can be called at any point during the lifetime of the Android app.
com.lispworks.Manager.init is asynchronous, in other words by the time it returns Lisp is not ready yet. com.lispworks.Manager.init optionally takes a Runnable
argument, which is called when LispWorks is ready. Alternatively the method com.lispworks.Manager.status can be used to determine when LispWorks is ready. See the entry for com.lispworks.Manager.init for more details.
com.lispworks.Manager.init loads LispWorks and initializes it. Apart from standard initialization and starting multiprocessing, the startup function also initializes the Java interface using init-java-interface, passing it the appropriate arguments. That includes passing the keyword :report-error-to-java-host
, which makes the function report-error-to-java-host invoke the user Java error reporters, and the keyword :send-message-to-java-host
which makes the function send-message-to-java-host call the Java method addMessage
. See Android Java classes and methods for the details.
The startup functions also set up a global "last chance" internal debugger hook, which is invoked once the debugger actually gets called (after any hooks you set up like error handlers, debugger wrappers and cl:*debugger-hook*
). The hook reports the error to the Java host (that is, invokes the user error reporters) and calls cl:abort
. If you did not define a cl:abort
restart, that will cause the current process to die, unless it is inside a call from Java, where it will cause this call to return. The return value is a zero of the correct type (see in Direct calls and Using proxies).
Once initialization finished, if a function was passed to deliver-to-android-project as its function argument, it is invoked asynchronously, and then the Runnable
which you passed to com.lispworks.Manager.init (if any) is invoked. From this point onwards, Lisp is ready to receive calls from Java, and can make calls into Java.
On Android when doing GUI operations it is essential to do them from the GUI thread, which is the main thread on Android. The functions android-funcall-in-main-thread and android-funcall-in-main-thread-list can be used to invoke a Lisp function on the main thread. To facilitate testing, these functions are also available on non-Android ports.
There is no proper debugger on Android itself, so it is important to ensure your code is working before delivering.
LispWorks User Guide and Reference Manual - 20 Sep 2017