![]() ![]() ![]() ![]() |
Implementing Native Methods |
Now that you've got a handle to a Java object in your native method, what can you do with it? You can use it to access the object's member [PENDING: is it true you can get class vars too?] variables. But first, you have to dereference the handle.Dereferencing the Handle
You apply theunhand()
macro to the object handle to dereference it. When you dereference a handle you get a pointer to a Cstruct
that parallels the Java object's structure. For example, to dereference the byte array, namedbuffer
, passed intoInputFile_read()
function you use theunhand()
macro like this:unhand(buffer)unhand()
returns a pointer to a C structure. You can use normal C syntax to access the elements in the structure. The elements in the structure parallel the member variables of the objects. Thus, you can access the member variables of an object through the pointer returned fromunhand()
.
Note: Theunhand()
macro is defined in the header fileinterpreter.h
which must be included in the C source file where the native method is implemented. This file is included into bothInputFileImpl.c
andOutputFileImpl.c
through the inclusion ofStubPreamble.h
.
Accessing the Object's Member Variables
You can use the pointer returned fromunhand()
like any other Cstruct
pointer and access its members with->
.
buffer
, in theInputFile_read()
function, is a byte array. The structure in C that maps to Java arrays contains an element namedbody
which is a C array of [PENDING: whatzits]. TheInputFile_read()
function gets a pointer to thebody
element ofbuffer
with this code:Now that thechar *data = unhand(buffer)->body;InputFile_read()
function has a C pointer to the body of the array, it can gleefully read bytes into it which it does with this line of code:Theactual = read(unhand(this)->fd, data, actual);struct
members have the same name as the corresponding variable in the Java class. So, you can use this same mechanism to access an InputFile object's member variables. Indeed, theInputFile_open()
function uses this mechanism to access an InputFile object'spath
andfd
variables:Note that the data type of a variable in the Clong InputFile_open(struct HInputFile *this) { int fd; char buf[MAXPATHLEN]; javaString2CString(unhand(this)->>path, buf, sizeof(buf)); convertPath(buf); fd = open(buf, O_RDONLY); if (fd < 0) return(FALSE); unhand(this)->>fd = fd; return(TRUE); }struct
is the nearest matching C data type to the Java type of the member variable in the object. Be sure to declare and use the structure elements with the correct data types. This table shows the correspondence between data types in Java and data types in C.Calling Java Methods from a Native Method
You can call a Java object's methods from a native method, but you use a different mechanism for that than you use for accessing its member variables. For example, thisThe interesting bits of thedoes not work. Rather you use one of the utility functions declared in [PENDING: where] for this purpose.ptr->methodname(); // doesn't workThe character-replacement program doesn't use any of these methods. So, let's look at another example that does. The new example program is a collection of methods that illustrate how you can perform various tasks from within a native method. Let's focus now on the method,
execute_java_dynamic_method()
- calls an instance method from a native method
execute_java_static_method()
- calls a class method from a native method
execute_java_constructor()
- creates a new Java object from within a native method
doubleUp()
, in the NativeExample class. The implementation of myValue)->value); twoX = (long)execute_java_dynamic_method( 0, (HObject *)hNewInst, "twoTimes", "()I"); unhand(unhand(hNewInst)->myValue)->value = twoX; return hNewInst; }doubleUp()
function are in bold.Calling a Java Constructor
Let's look at the first bold line in the code above--the call toexecute_java_constructor()
. Theexecute_java_constructor()
function requires four arguments, but may have more.The first argument to
execute_java_constructor()
is the Java environment [PENDING: environment of what?]. Most of the time, you will use "0" for the value of this argument to tell the Java runtime system to use the current Java environment.The second argument is the name of the class you want to instantiate. The example creates a new NativeExample object, so the value of the second argument in that example is the string "NativeExample".
The third argument is [PENDING: WHAT IS THIS?]
The fourth argument is the signature of the constructor that you want to call. This argument indicates whether there are any remaining arguments that need to be passed into
execute_java_constructor()
and how many. [PENDING: more here about this.]The general form of
execute_java_constructor()
is:The total number of arguments to the constructor is determined by the signature argument. The signature also indicates which of the classname constructors is called. This function returns the new object, or 0 if there is an error.HObject *execute_java_constructor(ExecEnv *env, char *classname, ClassClass *cb, char *signature, ...);Calling an Instance Method
After thedoubleUp()
function creates a new NativeExample object withexecute_java_constructor()
, it calls the object'stwoTimes()
instance method:ThetwoX = (long)execute_java_dynamic_method( 0, (HObject *)hNewInst, "twoTimes", "()I");execute_java_dynamic_method()
function requires four arguments, but may have more depending on which method you are calling.The first argument to
execute_java_dynamic_method()
is the same as the first argument toexecute_java_constructor()
--it's the Java environment. Again, most of the time, you will use "0" for the value of this argument to tell the Java runtime system to use the current Java environment.The second argument is the object whose instance method you want to execute. The third argument is the name of the instance method to execute. And finally, the fourth argument is the signature of the instance method. As with
execute_java_constructor()
the signature argument indicates if there are any remaining arguments, how many, and what type. You formulate the signature argument forexecute_java_dynamic_method()
as you did previously withexecute_java_constructor()
.The general form of
execute_java_dynamic_method()
is:long execute_java_dynamic_method(ExecEnv *env, HObject *obj, char *method_name, char *signature, ...);Calling a Class Method
To call a class method from a native method use:This function is analogous tolong execute_java_static_method(ExecEnv *env, ClassClass *cb, char *method_name, char *signature, ...);execute_java_dynamic_method
above, except that you provide a class instead of an object.
![]() ![]() ![]() ![]() |
Implementing Native Methods |