[[PageOutline]] = Java Foreign Function Interface = This page describes the API known as the Java FFI offered by ABCL to call arbitrary Java code. Unless otherwise noted, all the symbols are exported from the JAVA package, which is used by CL-USER. == The basics == The core API is based on Java reflection. Some operators come in two flavors: a concise one that leaves some things to be computed by ABCL at runtime, and a more efficient and verbose one, which is mostly a direct translation of the Java reflection API. All the operators that pass arguments to Java code can receive arbitrary Lisp objects, that will be automatically translated to appropriate Java objects when applicable (technically, by calling javaInstance() on them). For example, Lisp strings are translated to instances of java.lang.String. === Definitions === * ''Java object'': within ABCL, a Java object is an object of type JAVA-OBJECT. From the Java point of view, it is an instance of the class !JavaObject wrapping a native Java object. In this page, the expressions "an instance of the (Java) class X" or "an object of (Java) class X" should be read as "a JAVA-OBJECT wrapping an instance of/an object of...". Java objects are understood by DESCRIBE and INSPECT. * ''Java class designator'': either a string denoting the fully qualified name of a Java class, such as "java.lang.String", or a Java class metaobject, that is, an instance of java.lang.Class, for example as returned by the function `jclass`. * ''Java method designator'': in the context of Java method invocations, either a Java method metaobject (an instance of java.lang.reflect.Method), or a string representing the name of the method, for example "toString". * ''Java constructor designator'': in the context of Java object instantiations, either a Java constructor metaobject, or a Java class designator. === Function JCALL, JCALL-RAW === '''Syntax:''' '''jcall''' ''method instance &rest args => object'' '''jcall-raw''' ''method instance &rest args => JAVA-OBJECT'' '''Arguments and Values:''' `method` -- a Java method designator, that is, either a Java method metaobject (an instance of java.lang.reflect.Method), or a string representing the name of the method, for example "toString". `instance` -- the receiver object target of the method call. If the method is static, this argument is ignored and can be NIL. `args` -- the arguments passed to the method. '''Description:''' Reflectively calls a method and returns the result of the call. If `method` is a string, ABCL dynamically examines the class of `instance` to search for the most specific applicable method with that name, following Java overload resolution rules. If `method` is a Java method metaobject, it is called directly. `jcall` translates the result to a Lisp object if possible. `jcall-raw` performs no translation and always returns the original Java object. Note: `jcall` and other primitives that perform automatic method resolution are only capable of finding accessible (i.e., in general, public) methods. '''Examples:''' {{{ (jcall "toString" T) => "COMMON-LISP:T" (jcall-raw "toString" T) => # (jcall "compareTo" 12 24) => -1 ;;Resolves the method at runtime: inefficient but concise (jcall (jmethod "java.lang.Comparable" "compareTo" "java.lang.Object") 12 24) => -1 ;;Same as above, but avoiding dynamic method resolution }}} === Function JSTATIC, JSTATIC-RAW === '''Syntax:''' '''jstatic''' ''method class &rest args => object'' '''jstatic-raw''' ''method class &rest args => JAVA-OBJECT'' '''Arguments and Values:''' `method` -- a Java method designator. `class` -- a Java class metaobject. `args` -- the arguments passed to the method. '''Description:''' Reflectively calls a static method and returns the result of the call. `(jstatic method class args)` is equivalent to `(jcall (jmethod class method) nil args)` when `method` is a string, and to `(jcall method nil args)` when `method` is a Java method metaobject (class is thus ignored in that case). Similarly for the `-raw` variants. `jstatic` translates the result to a Lisp object if possible. `jstatic-raw` performs no translation and always returns the original Java object. '''Examples:''' {{{ (jstatic "getRuntime" "java.lang.Runtime") => # (jstatic-raw "getRuntime" "java.lang.Runtime") => # (jstatic "getRuntime" (jclass "java.lang.Runtime")) => # (jstatic (jmethod "java.lang.Runtime" "getRuntime") nil) => # }}} === Function JFIELD, JFIELD-RAW, (SETF JFIELD) === '''Syntax:''' '''jfield''' ''class-ref-or-field field-or-instance &optional instance value => object'' '''jfield-raw''' ''class-ref-or-field field-or-instance &optional instance value => JAVA-OBJECT'' (setf ('''jfield''' ''class-ref-or-field field-or-instance &optional (instance nil instance-supplied-p) unused-value'') ''newvalue'') '''Arguments and Values:''' `class-ref-or-field` -- depending on the usage pattern, a Java class designator or a string naming a field in a Java object. `field-or-instance` -- depending on the usage pattern, a Java object or a string naming a field in a Java object. `instance` -- a Java object. `value` -- an object; the new value of the field. `unused-value` -- ignored, present only to make `(setf jfield)` accept the same parameter patterns as `jfield`. '''Description:''' `jfield` is a complex operator supporting several usage patterns for reading the value of a Java field. For historical reasons, `jfield` can also be used to set the value of a field, but the more idiomatic form `(setf jfield)` should be preferred. These are the possible usages of `jfield`: For reading values: 1. `(jfield `''class-ref field''`)`: Retrieves the value of the static field `field` from class `class-ref`. 2. `(jfield `''field instance''`)`: Retrieves the value of the field `field` from the Java object `instance`. The class to which the field belongs is taken to be the class of `instance`. 3. `(jfield `''class-ref field instance''`)`: Retrieves the value of the field `field` of the class `class-ref` from the Java object `instance`. For storing values: 4. `(jfield `''class-ref field primitive-value''`)`: Stores `primitive-value` as the value of the static field `field` of class `class-ref`. 5. `(jfield `''field instance value''`)`: Stores `value` as the value of the field `field` in the Java object `instance`. The class to which the field belongs is taken to be the class of `instance`. 6. `(jfield `''class-ref field instance value''`)`: Stores `value` as the value of the field `field` of the class `class-ref` in the Java object `instance`. 7. `(jfield `''class-ref field''` NIL `''value''`)`: Stores `value` as the value of the static field `field` of class `class-ref`, when `value` could be confused with an instance (case 3). `(setf jfield)` can be used with patterns 1, 2 and 3 to store a value where `jfield` would have read it from. `jfield` translates the value of the field to a Lisp object when possible. `jfield-raw` performs no such translation. '''Examples:''' {{{ (jfield "java.lang.System" "out") => # (jfield "width" (jnew "java.awt.Dimension")) => 0 (let ((d (jnew "java.awt.Dimension"))) (setf (jfield "width" d) 42) (jcall "toString" d)) => "java.awt.Dimension[width=42,height=0]" }}} === Function JNEW === '''Syntax:''' '''jnew''' ''constructor &rest args => JAVA-OBJECT'' '''Arguments and Values:''' `constructor` -- a Java constructor designator (see [#Definitions Definitions]). `args` -- the arguments passed to the constructor. '''Description:''' Returns a new Java object created calling the specified constructor with the specified arguments. If `constructor` is a Java constructor metaobject, it will be called directly. If it is a Java class designator, the most specific constructor with respect to `args` will be searched in that class. '''Examples:''' {{{ (jnew "java.lang.String" "foo") => # (jnew (jclass "java.lang.String") "foo") => # (jnew (jconstructor "java.lang.String" "java.lang.String") "foo") => # }}} === Function JCLASS === '''Syntax:''' '''jclass''' ''name-or-class-ref &optional class-loader => a Java class metaobject'' '''Arguments and Values:''' `name-or-class-ref` -- a Java class designator (see [#Definitions Definitions]). `class-loader` -- the classloader to use to resolve the class. Refer to the section [#Classresolutionandloading Class resolution and loading]. '''Description:''' Returns a reference to the Java class designated by `name-or-class-ref`. If the `class-loader` parameter is passed, the class is resolved with respect to the given !ClassLoader. '''Examples:''' `(jclass "java.util.LinkedList") => #` === Function JMETHOD === '''Syntax:''' '''jmethod''' ''class-ref method-name &rest parameter-class-refs => a Java method metaobject'' '''Arguments and Values:''' `class-ref` -- a Java class designator. `method-name` -- a string, the name of the method. `parameter-class-refs` -- Java class designators representing the types of the method's arguments, in order. '''Description:''' Returns a reference to the public Java method named `method-name` in class `class-ref`, with the signature represented by `parameter-class-refs`. '''Examples:''' `(jmethod "java.util.LinkedList" "equals" "java.lang.Object") => #` === Function JCONSTRUCTOR === '''Syntax:''' '''jconstructor''' ''class-ref &rest parameter-class-refs => a Java constructor metaobject'' '''Arguments and Values:''' `class-ref` -- a Java class designator. `parameter-class-refs` -- Java class designators representing the types of the constructor's arguments, in order. '''Description:''' Returns a reference to the public Java constructor in the class `class-ref`, with the signature represented by `parameter-class-refs`. '''Examples:''' `(jconstructor "java.util.LinkedList" "java.util.Collection") => #` == Class resolution and loading == TODO == High-level constructs == TODO == CLOS integration == TODO == Implementing Java interfaces in Lisp == TODO == Defining Java classes in Lisp == See the [JavaFfi/RuntimeClass runtime-class] page for details. == A quick "cheat sheet": == ''(This is a very rough draft thrown together from an email by Alessio Stalla to the mailing list. It will be gradually superseded by the documentation above.)'' `(jclass )`:: gives you a Java class `(jmethod <&rest argument types>)`:: gives you a method `(jconstructor <&rest argument types>)`:: a constructor `(jnew <&rest arguments>)`:: instantiates a new Java object `(jcall <&rest arguments>)`:: calls a method `jstatic`:: to access static fields and methods. `jfield`:: to access fields. `jproperty-value` and `(setf jproperty-value)`:: access "properties" following the Java Bean convention (setXXX and getXXX). That's almost all; there is some more advanced stuff (e.g. manipulating Java arrays). You can find most or all of this stuff inside [http://trac.common-lisp.net/armedbear/browser/trunk/abcl/src/org/armedbear/lisp/Java.java Java.java]. It's not documented but quite readable. For example code that uses the Java FFI API, see [http://trac.common-lisp.net/armedbear/browser/trunk/abcl/examples the examples]. ''(The rest of the page is taken from the symbols and comments in [http://trac.common-lisp.net/armedbear/browser/trunk/abcl/src/org/armedbear/lisp/Java.java Java.java]. Still needs a lot of work, obviously.)'' '''`register-java-exception` ''exception-name condition-symbol'' => `T` or `NIL`''' Registers the Java Throwable ''exception-name'' as the condition designated by ''condition-symbol''. '''`unregister-java-exception` ''exception-name'' => `T` or `NIL`''' Unregisters the Java Throwable ''exception-name'' previously registered by `register-java-exception`. '''jfield` ''class-ref-or-field field-or-instance'' &optional ''instance value'' ''' '''`jfield-raw` ''class-ref-or-field field-or-instance'' &optional ''instance value'' ''' Retrieve or modify a field in a Java class or instance. Supported argument patterns: ''class-ref field-name'':: Retrieve the value of a static field. ''class-ref field-name instance-ref'':: Retrieve the value of a class field of the instance. ''class-ref field-name primitive-value'':: Store ''primitive-value'' in a static field. ''class-ref field-name instance-ref value'':: Store ''value'' in a class field of the instance. ''class-ref field-name nil value'':: Store ''value'' in a static field (when value may be confused with an ''instance-ref''). ''field-name instance'':: Retrieve the value of a field of ''instance''. The class is derived from ''instance''. ''field-name instance value'':: Store ''value'' in a field of ''instance''. The class is derived from ''instance''. ''' `jconstructor` ''class-ref'' &rest ''parameter-class-refs'' => ''constructor-ref'' ''' Returns a reference to the Java constructor of ''class-ref'' with the given ''parameter-class-refs''. ''' `jmethod` ''class-ref method-name'' &rest ''parameter-class-refs'' => ''method-ref'' ''' Returns a reference to the Java method ''method-name'' of ''class-ref'' with the given ''parameter-class-refs''. ''' `jstatic` ''method-ref class-ref'' &rest ''args'' => ''result'' ''' ''' `jstatic-raw` ''method-ref class-ref'' &rest ''args'' ''result'' ''' ''' `jnew` ''constructor'' &rest ''args'' => ''object'' ''' Invokes the Java constructor ''constructor'' with the arguments ''args'' ''' `jnew-array` ''element-type'' &rest ''dimensions'' => ''array-object'' ''' Creates a new Java array of type ''element-type'', with the given ''dimensions''. ''' `jarray-ref` ''java-array'' &rest ''indices'' => ''object'' ''' Dereference the Java array ''java-array'' using the given ''indices'', coercing the result into a Lisp type, if possible. ''' `jarray-ref-raw` ''java-array'' &rest ''indices'' => ''object'' ''' Dereference the Java array ''java-array'' using the given ''indices''. Does not attempt to coerce the result into a Lisp type. ''' `jarray-set` ''java-array new-value'' &rest ''indices'' => ''new-value'' ''' ''' `jcall` ''method-ref instance'' &rest ''args'' => ''result'' ''' ''' `jcall-raw` ''method-ref instance'' &rest ''args'' => ''result'' ''' `jcall` calls makeLispObject() to convert the result to an appropriate Lisp type. `jcall-raw` does no type conversion. The result of the call is simply wrapped in a JavaObject. (This is true for all the `-raw` variants.) ''' `make-immediate-object` ''object'' &optional ''type'' => ''object'' ''' ''' `java-object-p` ''object'' => `T` or `NIL` ''' Returns `T` if ''object'' is an instance of JavaObject (as opposed to a Lisp object). ''' `jobject-lisp-value` ''java-object'' => ''lisp-object'' ''' Returns the Lisp object corresponding to (wrapping?) the JavaObject. I.e. `return JavaObject.getInstance(arg.javaInstance(), true);` ''' `jcoerce` ''object'' ''intended-class'' => ''java-object'' ''' Attempts to coerce ''object'' into a JavaObject of class ''intended-class''. Raises a `type-error` if no conversion is possible. ''' `%jget-property-value` ''java-object property-name'' ''' Use `jproperty-value` instead. ''' `%jset-property-value` ''java-object property-name value'' ''' Use `(setf jproperty-value)` instead. ''' `jrun-exception-protected` ''closure'' '''