# Changeset 13335

Ignore:
Timestamp:
06/16/11 14:56:43 (12 years ago)
Message:

Fold freestanding documentation into the Manual.

Location:
trunk/abcl/doc
Files:
1 deleted
1 edited

### Legend:

Unmodified
 r13334 \end{itemize} \subsubsection{Lisp FFI} FFI stands for "Foreign Function Interface", which is the way the contemporary Lisp world refers to methods of "calling out" from Lisp into "foreign" langauges and envrionments.  This document describes the various ways that one interacts with Lisp world of Abcl from Java, considering the hosted Lisp as the "Foreign Function" that needs to be "Interfaced". \subsubsubsection{Calling Lisp from Java} Note: As the entire ABCL Lisp system resides in the org.armedbear.lisp package the following code snippets do not show the relevant import statements in the interest of brevity. Per JVM, there can only ever be a single Lisp interpreter.  This is started by calling the static method Interpreter.createInstance(). \begin{code}{java} Interpreter interpreter = Interpreter.createInstance(); \end{code} If this method has already been invoked in the lifetime of the current Java process it will return null, so if you are writing Java whose lifecycle is a bit out of your control (like in a Java servlet), a safer invocation pattern might be: \begin{code}{java} Interpreter interpreter = Interpreter.getInstance(); if (interpreter == null) { interpreter = Interpreter.createInstance(); } \end{code} The Lisp EVAL primitive may be simply passed strings for evaluation, as follows \begin{code}{java} String line = "(load \"file.lisp\")"; LispObject result = interpreter.eval(line); \end{code} Notice that all possible return values from an arbitrary Lisp computation are collapsed into a single return value.  Doing useful further computation on the LispObject depends on knowing what the result of the computation might be, usually involves some amount of instanceof introspection, and forms a whole topic to itself (c.f. [Introspecting a LispObject](#introspecting)). Using EVAL involves the Lisp interpreter.  Lisp functions may be directly invoked by Java method calls as follows.  One simply locates the package containing the symbol, then obtains a reference to the symbol, and then invokes the execute() method with the desired parameters. \begin{code}{java} interpreter.eval("(defun foo (msg) (format nil \"You told me '~A'~%\" msg))"); Package pkg = Packages.findPackage("CL-USER"); Symbol foo = pkg.findAccessibleSymbol("FOO"); Function fooFunction = (Function)foo.getSymbolFunction(); JavaObject parameter = new JavaObject("Lisp is fun!"); LispObject result = fooFunction.execute(parameter); // How to get the "naked string value"? System.out.prinln("The result was " + result.writeToString()); \end{code} If one is calling an primitive function in the CL package the syntax becomes considerably simpler if we can locate the instance of definition in the ABCL source, we can invoke the symbol directly.  To tell if a LispObject contains a reference to a symbol. \begin{code}{java} boolean nullp(LispObject object) { LispObject result = Primitives.NULL.execute(object); if (result == NIL) { return false; } return true; } \end{code} /subsubsubsection{Introspecting a LispObject} We present various patterns for introspecting an an arbitrary LispObject which can represent the result of every Lisp evaluation into semantics that Java can meaniningfully deal with. /subsubsubsubsection{LispObject as \java{boolean}} If the LispObject a generalized boolean values, one can use \java{getBooleanValue()} to convert to Java: \begin{code}{java} LispObject object = Symbol.NIL; boolean javaValue = object.getBooleanValue(); \end{code} Although since in Lisp, any value other than NIL means "true", the use of Java equality it quite a bit easier and more optimal: \begin{code}{java} boolean javaValue = (object != Symbol.NIL); \end{code} /subsubsubsubsection{LispObject is a list} If LispObject is a list, it will have the type Cons.  One can then use the copyToArray[] to make things a bit more suitable for Java iteration. \begin{code}{java} LispObject result = interpreter.eval("'(1 2 4 5)"); if (result instanceof Cons) { LispObject array[] = ((Cons)result.copyToArray()); ... } \end{code} A more Lispy way to iterated down a list is to use the cdr() access function just as like one would traverse a list in Lisp:; \begin{code}{java} LispObject result = interpreter.eval("'(1 2 4 5)"); while (result != Symbol.NIL) { doSomething(result.car()); result = result.cdr(); } \end{code} \subsection{JAVA}