All Manuals > LispWorks® User Guide and Reference Manual > 40 Java classes and methods

com.lispworks.LispCalls Java Class

Summary

public class com.lispworks.LispCalls implements InvocationHandler

The Java class com.lispworks.LispCalls defines methods for calling from Java to Lisp.

com.lispworks.LispCalls is part of the LispWorks distribution. For Android it is part of the 8-0-0-0/etc/lispworks.aar file. See the 16 Android interface for details. On other platforms it is defined in the JAR file lispcalls.jar which is part of the LispWorks distribution in the etc directory, that is (lispworks-file "etc/lispcalls.jar"). This JAR file needs to be on the classpath (for example by the keyword argument :java-class-path to init-java-interface).


com.lispworks.LispCalls.callIntV

com.lispworks.LispCalls.callIntA

com.lispworks.LispCalls.callDoubleV

com.lispworks.LispCalls.callDoubleA

com.lispworks.LispCalls.callObjectV

com.lispworks.LispCalls.callObjectA

com.lispworks.LispCalls.callVoidV

com.lispworks.LispCalls.callVoidA Methods

public static int callIntV(String name, Object... args)

public static int callIntA(String name, Object[] args)

public static double callDoubleV(String name, Object... args)

public static double callDoubleA(String name, Object[] args)

public static Object callObjectV(String name, Object... args)

public static Object callObjectA(String name, Object[] args)

public static void callVoidV(String name, Object... args)

public static void callVoidA(String name, Object[] args)

Description

The <type> in each method name call<type>[VA], the type specifies the return type, and V or A specifies whether the arguments are supplied as Variable arguments or Array. Otherwise the pairs of V and A methods behave the same.

name argument is a string specifying a Lisp symbol. The name is parsed by a simple parser as described for com.lispworks.LispCalls.checkLispSymbol (with fboundp = true).

If the symbol is not found or is not fbound, these methods throw a RuntimeException with a string giving the reason for failure.

If the symbol is found, it is applied to the arguments args. For each argument, if it is a primitive type or of a class corresponding to a primitive type or a string, it is converted to the corresponding Lisp value. Otherwise it is passed as a jobject. See 15.1 Types and conversion between Lisp and Java. The result of the call is converted to the return type of the method and returned from the method. The conversion of the result type allows any float to be returned as a double, but does not coerce between integers and floats. For the Object return value, the result must be either a Java object (jobject or an instance of standard-java-object), or a Lisp object that can be converted to a Java object. See 15.1 Types and conversion between Lisp and Java.

The Lisp function is an ordinary Lisp function, but it needs to return the right value. Unless the call is using the Void callers (com.lispworks.LispCalls.callVoidA or com.lispworks.LispCalls.callVoidV), returning the wrong value will call the java-to-lisp-debugger-hook (see init-java-interface) with an appropriate condition, and then return zero of the correct type (that is 0, 0d0 or Java null) from the call.

The call to the Lisp function is wrapped such that trying to throw out of it does not actually finish the throw, and instead returns zero of the correct type from the call. It is also wrapped by a debugger hook, which is invoked if the code tries to enter the debugger (normally as a result of an unhandled error, but could be any call to cl:invoke-debugger). The hook calls the java-to-lisp-debugger-hook (see init-java-interface) with the condition, and then calls cl:abort. If there is no cl:abort restart inside the Lisp function that catches this abort, this causes returning a zero of the correct type.

An important issue to remember is that when delivering with shaking, LispWorks eliminates symbols for which there is no reference. If the only call to a Lisp symbol foo is from Java, LispWorks will not see the reference and it will eliminate foo. To guard against this, you can either pass foo in a list to the deliver keyword :keep-symbols, or more conveniently, use the function hcl:deliver-keep-symbols (see the Delivery User Guide), for example:

(defun function-called-from-java (arg1 arg2)
  ...
  )
 
(deliver-keep-symbols 'function-called-from-java)
Examples
int sum = com.lispworks.LispCalls.callIntV("+", 2, 3, 10);
=> sum = 15
 
int position = com.lispworks.LispCalls.callIntV("search", "r", "international");
=> position = 4
double logThree = com.lispworks.LispCalls.callDoubleV("log",  3);
=> logThree = 1.0986123

com.lispworks.LispCalls.checkLispSymbol Method

public static boolean checkLispSymbol(String name, boolean fboundp)

Description

Checks whether a Lisp symbol exists, and optionally whether it is fbound.

name specifies the name of the Lisp symbol. The string name is parsed in a simple way, rather than using the Lisp reader. The parsing involves:

  1. Upcase the string.
  2. If there is a colon, take the part before it as a package name. Otherwise use "COMMON-LISP-USER" as the package name.
  3. If the colon is followed by another colon, skip it and set a flag allowing internals. Otherwise, set a flag allowing only externals.
  4. Take the rest of the string as the symbol name.
  5. Find the package from the package name.
  6. Find the symbol using the package and the symbol name. If it is internal, use it only if the flag allowing internal was set.
  7. If fboundp is true, check whether the symbol is fbound.

If all these steps succeed, checkLispSymbol returns true. Otherwise it returns false.

For symbols with names that do not need escaping, the result is the same normal processing by the Lisp reader without interning when there is no symbol.

checkLispSymbol caches the results in the Java side, which means that if the symbol appears or gets defined after the first call to checkLispSymbol it may return the wrong result.

See also

15.3 Calling from Java to Lisp
init-java-interface
define-lisp-proxy
deliver


com.lispworks.LispCalls.createLispProxy Method

public static native Object createLispProxy(String name)

Description

Creates a Lisp proxy, which is a Java proxy which calls Lisp functions.

name specifies a symbol which is the name of a proxy definition, defined in Lisp by either define-lisp-proxy or setup-lisp-proxy. name is parsed by a simple parser as described for com.lispworks.LispCalls.checkLispSymbol (with fboundp = false).

Once it found the symbol, it makes a proxy the same way that calling make-lisp-proxy with name would, and returns it. The result is an Object that implements all the interfaces that are defined in the proxy definition, and when the methods of these interfaces are called on the object it calls into Lisp. See define-lisp-proxy for details.

If createLispProxy is successful it returns the proxy object. If there is any problem, this will cause a call to cl:error. If the cl:error call is not handled, the java-to-lisp-debugger-hook (see init-java-interface) is called with the condition, and then null is returned from createLispProxy. If the error is handled and tries to throw out of the context of the Lisp side of createLispProxy, the throw is blocked and createLispProxy returns null.


com.lispworks.LispCalls.waitForInitialization Method

static public boolean waitForInitialization()

static public boolean waitForInitialization(long seconds)

static public boolean waitForInitialization(long timeout , java.util.concurrent.TimeUnit unit)

Description

Waits for a LispWorks dynamic library to finish initialization and accept foreign calls.

Note: You should not call waitForInitialization from the main thread on Android. Use the methods in com.lispworks.Manager instead, in particular com.lispworks.Manager.init and com.lispworks.Manager.status. If you call waitForInitialization from a non-main thread on Android, then this must be after the call to com.lispworks.Manager.init.

The method without arguments waits for up to 10000 seconds. The method that takes long waits for up to seconds seconds. The method that takes long and java.util.concurrent.TimeUnit waits for up to the period defined by timeout and unit. See the Java documentation for the possible values of java.util.concurrent.TimeUnit.

waitForInitialization returns when LispWorks has finished its initialization or when the wait period has passed. If LispWorks finishes its initialization first, waitForInitialization returns true. If the wait period has passed, waitForInitialization returns false.

When waitForInitialization is called with 0 seconds, it returns immediately with true if LispWorks is already initialized, and false otherwise. Thus it can be used as a predicate without waiting.

Notes

Until LispWorks finishes its initialization, calls into LispWorks from Java using the other methods in com.lispworks.LispCalls hang, and raise an exception if hanging for too long. If this is an acceptable behavior, then you do not need waitForInitialization. If this is not acceptable, waitForInitialization allows you to check and avoid this situation. Typically your code will do something like:

if (com.lispworks.LispCalls.waitForInitialization(1))
  com.lispworks.LispCalls.callIntV("A-LISP-FUNCTION");
else
  do_something_else();

If the LispWorks dynamic library was created with synchronous initialization (the default), then by the time the loading method (normally System.loadLibrary or System.load) returns, LispWorks has finished initializing. In this case you need waitForInitialization only in code that does not know if the loading method has returned (or even called at all).

If the LispWorks dynamic library was created with asynchronous initialization (setup-deliver-dynamic-library-for-java was called with true for asynchronous), the loading method returns immediately, and LispWorks initializes asynchronously. In this situation you can be sure that LispWorks finished initializing only after a call to waitForInitialization has returned true.

If you don't know how the LispWorks dynamic library was created, just assume that it is asynchronous and always check using waitForInitialization.

See also

setup-deliver-dynamic-library-for-java


LispWorks® User Guide and Reference Manual - 01 Dec 2021 19:30:50