Introduction
Exercise 1
Exercise 2
Exercise 3
These exercises demonstrate a few techniques used with JNI programming.
This exercise demonstrates how to pass an argument from Java to a function implemented in C++.
- Declare a native method in Java
- Implement a native method in C++
- Pass arguments to native code from Java
- Pass values back to Java from native code
Implement a C++ function that calculates the area of circle and call it from Java code. A calculation is performed in the C++ function and the result is passed back to the Java code. The C++ function implements a native method:
double calculateAreaOfCircle(int radius);which, as you would expect, calculates the area of a circle given its radius.Please follow the link to the exercise 1 page.
This exercise demonstrates how to call a Java method from C++ code.
- Access Java environment from C++ code
- Invoke Java methods from C++ code
- Pass parameters to Java methods
When a native function is called, two "hidden" arguments are passed in to the function along with the programmer's arguments. Recall the native method from the HelloWorld example:
The two parameters, env and obj were not passed by the caller and were not used by the function, yet they are required in the definition. The first parameter is a pointer to the Java environment (JVM) at runtime and the second is a reference to the Java object that called this native method. In the HelloWorld example the object was an instance of the HelloWorld class.JNIEXPORT void JNICALL Java_HelloWorld_displayMessage(JNIEnv *env, jobject obj)In this exercise we will need to use these arguments in order to call a Java method from C++. There are basically three steps that must be taken in order for C++ to call a Java method. The sample calls below assume that there is a Java method called calculateAreaOfCircle that takes a double as a parameter and returns a double.
- Get the class associated with the calling object by invoking a method of the env object called GetObjectClass and passing the object to the function.
jclass cls = env->GetObjectClass(obj);- Get the ID for the method you wish to call by invoking a method of the env object called GetMethodID and passing the class of the object, the name of the method, and the method's signature.
jmethodID mid = env->GetMethodID(cls, "calculateAreaOfCircle", "(D)D");- Invoke the method by calling CallXXXXMethod, where XXXX is the return type of the Java method. In this example, the function returns a double. You pass the object and the method ID followed by the actual parameters to the function.
Please follow the link to the exercise 2 page.jdouble area = env->CallDoubleMethod(obj, mid, radius);
This exercise demonstrates how to access Java fields from C++ code.To set Java fields from C++, you call the corresponding functions for static and non-static fields:
- Get Java fields from C++ code
- Set Java fields from C++ code
Accessing Java fields from native code is similar to invoking Java methods from native code; you use JNI API functions. Suppose you have a Java class:
and assume you have a C++ function such as this:class MyClass { public int x; // non-static public field static public int y; // static public field }To access a non-static field from C++, you would need to perform these calls within the native method:JNIEXPORT void JNICALL Java_MyClass_SomeFunc(JNIEnv *env, jobject obj)
To access a static field from C++, you would need to perform step one above, but steps two and three are slightly different:
- Get the class associated with the calling object by invoking a method of the env object called GetObjectClass and passing the object to the function.
jclass cls = env->GetObjectClass(obj);- Get the ID for the non-static field you wish to access by invoking a method of the env object called GetFieldID and passing the class of the object, the name of the field, and the field's signature. The signature for a field is its data type.
jfieldID fid = env->GetFieldID(cls, "x", "I");- To get the value from the field, you call GetXXXXField, where XXXX is the type of the field. You need to supply the object and the field ID. In this example, the field is an integer.
jint x = env->GetIntField(obj, fid);
- Same as above.
- Get the ID for the static field you wish to access by invoking a method of the env object called GetStaticFieldID and passing the class of the object, the name of the static field, and the field's signature.
jfieldID fid = env->GetStaticFieldID(cls, "y", "I");- To get the value from the field, you call GetStaticXXXXField, where XXXX is the type of the field. You need to supply the class (static fields are class fields) and the field ID. In this example, the field is an integer.
jint x = env->GetStaticIntField(cls, fid);
env->SetIntField(obj, fid, value); // for non-static fields env->SetStaticIntField(cls, fid, value); // for non-static fields
Copyright © 1998
Sergio Antoy.
All Rights Reserved February 99, version 020199 |