Many implementations of a high-level language provide an interface
to functions written in a lower-level language, usually C.
Kawa has such a “Foreign Function Interface”,
but the lower-level language it targets is Java.
A PrimProcedure
is a Procedure
that invokes a specified Java method.
public class PrimProcedure extends ProcedureN { ...; Method method; Type retType; Type[] argTypes; }
The following syntax evaluates to a PrimProcedure
such that when you call it, it will invoke
the static method named method-name
in class class
with the given arg-type
s
and result-type
:
(primitive-static-methodclass
method-name
return-type
(arg-type
...))
When such a function is called, Kawa makes sure to convert the arguments and result between the Scheme types and Java types. For example:
(primitive-static-method <java.lang.Character> "toUpperCase" <char> (<char>))
This is a function that converts a Scheme character
(represented using a <kawa.lang.Char>
object),
to a Java char
, applies the
standard java.lang.Character.toUpperCase
method,
and converts the result back to a Scheme character.
Normally, the Java reflection features are used to call the
specified method. However, if the primitive-static-method
is used directly in the function position of an application,
then the compiler is able to inline the PrimProcedure
,
and emit efficient invokestatic
bytecode operations.
That is the usual style, which is used to define
many of the standard Scheme procedures,
such as here char-upcase
:
(define (char-upcase ch) ((primitive-static-method <java.lang.Character> "toUpperCase" <char> (<char>)) ch))
Similar forms primitive-virtual-method
and
primitive-interface-method
are used to generate virtual method calls and interface calls,
while primitive-constructor
is used to
create and initialize a new object.
You can access instance and static fields of an object using
similar macros. For example, to get the time-stamp from an
Event
, do:
((primitive-get-field <java.lang.Event> "when" <long>) evt)
Kawa also has low-level operations for working with Java arrays. All these primitive operations are inlined to efficient byte code operations when the compiler knows that the procedure being called is a primitive; otherwise, the Java reflection features are used.