Previous | Next | Trail Map | Integrating Native Methods into Java Programs | Implementing Native Methods


Returning a Value from a Native Method

You can return a value of any type from a native method including primitive types such as int, float, boolean, or reference types such as objects, arrays or strings.

Returning Primitive Types

You specify the return type for a native method in the Java definition for the method. The InputFile class has two native methods that return values. The open() method returns a boolean and the read() method returns an integer.
    // in InputFile.java
public native boolean open();
public native int read(byte b[], int len);
And the OutputFile class has two native methods that return values. The open() method returns a boolean and the write() method returns an integer.
    // in OutputFile.java
public native boolean open();
public native int write(byte b[], int len);
As with parameters passed into native methods, the data types of the return values from the native method may not match that accepted by the calling Java program. This table shows the correspondence between types in Java and types in C. You must use the mappings in this table to return the correct data from a native method written in C.

Note from the table that Java booleans and Java integers both map to C longs. So all of these functions return long values.

    // in InputFileImpl.c
long InputFile_open(struct HInputFile *this)
    . . .
long InputFile_read(struct HInputFile *this,
                    HArrayOfByte *buffer,
                    long count)

    // in OutputFileImpl.c
long OutputFile_write(struct HOutputFile *this,
                      HArrayOfByte *buffer,
                      long count)
    . . .
long OutputFile_open(struct HOutputFile *this)

Returning Complex Types

[PENDING: I made this stuff up. Is it true?]

You can also use a native method's return value to return a reference data type. Neither the InputFile class nor the OutputFile class do this. However, suppose that the read() method in the InputFile class returned the bytes read via the method's return value. The Java declaration of that method would be:

    // in InputFile.java
public native byte[] read(int len);
This statement declares that the read() method returns an array of bytes. The native language function that implements read() must now be declared to return an array of bytes. The return values for reference data types follow the same rules that arguments of reference data types follow. The native language function must be declared to return a handle to a structure. The structure name is derived from the class name as described in Passing Complex Data Types. Thus the new declaration for the InputFile_read() function would be:
    // in InputFileImpl.c
HArrayOfByte * InputFile_read(struct HInputFile *this,
                    long count)

Returning Data Through Arguments to Native Methods

Sometimes, it's more convenient to return data through the arguments to a native method rather than through the return value, such as when you have more than one data value to return.

Primitive data types are passed into a native method by value. That is, the value of the argument is put on the call stack not a reference to it. Thus, you cannot return a value from a native method through an argument with a primitive data type--you must return it through an argument with a reference data type. The read() method in InputFile does this--it returns the bytes read through its byte array argument. The InputFile_read() function gets the bytes from the input file and places them into the body of the byte array.

If you want to return a primitive value, consider using the return value of the function. If you really must use an argument to return a primitive value, then you must wrap it in one of java.lang's data type wrapper classes such as Integer, Float, or Boolean.


Previous | Next | Trail Map | Integrating Native Methods into Java Programs | Implementing Native Methods