While Toba is designed primarily for programs written in Java, the addition of native functions written in C is not difficult. However, the interface differs from the Sun native interface.
This page notes some key points of the native code interface,
but it is not a complete tutorial.
The prospective native coder should also study
the data structures defined in toba.h
,
found in the runtime directory of the Toba package.
Some examples of native code may be found in the runtime directory;
these files implement portions of the Java API.
The include file toba.h
defines general types and
data structures.
Each method parameter is one of the types
Int, Long, Float, Double, or Object.
Return types are any of those or Void.
Other integral types are passed as Int.
Object pointers represent all reference types including arrays.
All object structures begin with a class pointer;
for any object pointer o
, the expression
(((struct in_generic *)o)->class)
produces a Class pointer to the structure containing information
about the class.
This structure is described in toba.h
.
Arrays are indicated by the IS_ARRAY
bit in the flags
field of the class structure.
For arrays, the elemclass
field points to the
class structure giving the array element type.
If the array elements are a Java primitive type,
the IS_PRIMITIVE
flag is set in elemclass->flags
.
Data structures specific to a particular class are defined in the
classname.h
file, with underscores replacing periods in
the class name.
The class structure is a global variable named cl_
classname;
it contains class information, instance function pointers, and
any static variables.
The structure of an object instance is defined by
struct in_
classname.
The C code for a native method has a name that is
derived from the method name.
The C name includes a hash code that also factors in the
class name and method signature.
The hash code differentiates overloaded methods and
like-named methods of different classes.
The name hashing also allows native implementations of
methods having names (such as häagen_dazs()
) that are
illegal in C.
The C form of a name is found by compiling with toba -C the Java code that declares the native method. This produces a classname.h file containing the proper prototype.
If a native method is declared synchronized, a wrapper function
with the stated name is generated; it calls the actual native function,
having the same name but prefixed by sy_
.
Each native code file begins by including general and class-specific definitions:
The classname.h file must be present when native code is compiled. This is arranged automatically if the Java and C code are built together by a command such as#include <toba.h>
classname
#include ".h"
toba maincode.java native.c
.
Every native method is a C function. The actual code can be very simple. Instance methods have an implicit initial this parameter, but there are no other hidden parameters.
Here is an example of a simple but complete native static function:
Int getpid__9zIGm(void)
{
return getpid();
}
Exceptions can be thrown by calling athrow(e)
where
e
is the actual exception object.
The hard part is constructing this object; try writing that
first in Java and looking at the corresponding C code produced by
toba -C.
Every class must be initialized before it is used. Generally,
this is done by Toba automatically. However, it is up to the
programmer to make sure that a class has been initialized before
it is accessed from native code. A class must be initialized
by calling the initclass
function at least once before
the first use of any field or method in the class.
It is safe to call initclass
on the same class more than
once.
If the class of a native method contains initialization code
in the form of a <clinit>
method,
this code must be called on entry to any static method.
The easiest way to accomplish this is to begin every static method with
which expands to an initialization call only if the class actually needs it.init_
classname();
Initialization code is not needed in instance functions. If an instance of a class exists, as is necessary to call such a function, then the class must already have been initialized.
Static final variables that are initialized with compile-time constant expressions appear to native methods to be uninitialized. We are investigating possible solutions to this problem.
The Toba library contains a number of helper functions written to support the generated code and the API library. These helper functions are available for use by native methods.
For existing methods written to the Sun interface, a conversion guide notes some correspondences between Sun and Toba helper functions.
A simple example illustrates the coding of a native method.