Changeset 13335
- Timestamp:
- 06/16/11 14:56:43 (12 years ago)
- Location:
- trunk/abcl/doc
- Files:
-
- 1 deleted
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/abcl/doc/manual/abcl.tex
r13334 r13335 78 78 \end{itemize} 79 79 80 \subsubsection{Lisp FFI} 81 82 FFI stands for "Foreign Function Interface", which is the way the 83 contemporary Lisp world refers to methods of "calling out" from Lisp 84 into "foreign" langauges and envrionments. This document describes 85 the various ways that one interacts with Lisp world of Abcl from Java, 86 considering the hosted Lisp as the "Foreign Function" that needs to be 87 "Interfaced". 88 89 90 \subsubsubsection{Calling Lisp from Java} 91 92 Note: As the entire ABCL Lisp system resides in the org.armedbear.lisp 93 package the following code snippets do not show the relevant import 94 statements in the interest of brevity. 95 96 Per JVM, there can only ever be a single Lisp interpreter. This is 97 started by calling the static method `Interpreter.createInstance()`. 98 99 \begin{code}{java} 100 Interpreter interpreter = Interpreter.createInstance(); 101 \end{code} 102 103 If this method has already been invoked in the lifetime of the current 104 Java process it will return null, so if you are writing Java whose 105 lifecycle is a bit out of your control (like in a Java servlet), a 106 safer invocation pattern might be: 107 108 \begin{code}{java} 109 Interpreter interpreter = Interpreter.getInstance(); 110 if (interpreter == null) { 111 interpreter = Interpreter.createInstance(); 112 } 113 \end{code} 114 115 116 117 The Lisp `EVAL` primitive may be simply passed strings for evaluation, 118 as follows 119 120 \begin{code}{java} 121 String line = "(load \"file.lisp\")"; 122 LispObject result = interpreter.eval(line); 123 \end{code} 124 125 126 Notice that all possible return values from an arbitrary Lisp 127 computation are collapsed into a single return value. Doing useful 128 further computation on the `LispObject` depends on knowing what the 129 result of the computation might be, usually involves some amount 130 of instanceof introspection, and forms a whole topic to itself 131 (c.f. [Introspecting a LispObject](#introspecting)). 132 133 Using `EVAL` involves the Lisp interpreter. Lisp functions may be 134 directly invoked by Java method calls as follows. One simply locates 135 the package containing the symbol, then obtains a reference to the 136 symbol, and then invokes the `execute()` method with the desired 137 parameters. 138 139 \begin{code}{java} 140 interpreter.eval("(defun foo (msg) (format nil \"You told me '~A'~%\" msg))"); 141 Package pkg = Packages.findPackage("CL-USER"); 142 Symbol foo = pkg.findAccessibleSymbol("FOO"); 143 Function fooFunction = (Function)foo.getSymbolFunction(); 144 JavaObject parameter = new JavaObject("Lisp is fun!"); 145 LispObject result = fooFunction.execute(parameter); 146 // How to get the "naked string value"? 147 System.out.prinln("The result was " + result.writeToString()); 148 \end{code} 149 150 If one is calling an primitive function in the CL package the syntax 151 becomes considerably simpler if we can locate the instance of 152 definition in the ABCL source, we can invoke the symbol directly. To 153 tell if a `LispObject` contains a reference to a symbol. 154 155 \begin{code}{java} 156 boolean nullp(LispObject object) { 157 LispObject result = Primitives.NULL.execute(object); 158 if (result == NIL) { 159 return false; 160 } 161 return true; 162 } 163 164 \end{code} 165 166 /subsubsubsection{Introspecting a LispObject} 167 168 We present various patterns for introspecting an an arbitrary 169 `LispObject` which can represent the result of every Lisp evaluation 170 into semantics that Java can meaniningfully deal with. 171 172 /subsubsubsubsection{LispObject as \java{boolean}} 173 174 If the LispObject a generalized boolean values, one can use 175 \java{getBooleanValue()} to convert to Java: 176 177 \begin{code}{java} 178 LispObject object = Symbol.NIL; 179 boolean javaValue = object.getBooleanValue(); 180 \end{code} 181 182 Although since in Lisp, any value other than NIL means "true", the 183 use of Java equality it quite a bit easier and more optimal: 184 185 \begin{code}{java} 186 boolean javaValue = (object != Symbol.NIL); 187 \end{code} 188 189 /subsubsubsubsection{LispObject is a list} 190 191 If LispObject is a list, it will have the type `Cons`. One can then use 192 the `copyToArray[]` to make things a bit more suitable for Java 193 iteration. 194 195 \begin{code}{java} 196 LispObject result = interpreter.eval("'(1 2 4 5)"); 197 if (result instanceof Cons) { 198 LispObject array[] = ((Cons)result.copyToArray()); 199 ... 200 } 201 \end{code} 202 203 A more Lispy way to iterated down a list is to use the `cdr()` access 204 function just as like one would traverse a list in Lisp:; 205 206 \begin{code}{java} 207 LispObject result = interpreter.eval("'(1 2 4 5)"); 208 while (result != Symbol.NIL) { 209 doSomething(result.car()); 210 result = result.cdr(); 211 } 212 \end{code} 213 214 80 215 \subsection{JAVA} 81 216
Note: See TracChangeset
for help on using the changeset viewer.