Data interaction between Java and C/C++ using JNI
I recently worked on a Tiemsten database project that involved using JNI (Java Native Interface) technology. In this project, we used Java to develop the user interface and business logic, while C was used for implementing the ODBC access layer of the database. Although writing simple ODBC code is not particularly challenging, transferring data between Java and C can be quite complex. There are several common scenarios for data exchange between Java and C, including passing basic data types, handling object types, returning objects from C to Java, and even invoking Java classes from C. Below, I’ll walk through these cases in detail.
1. Passing Basic Data Types from Java to C
For basic data types, Java and C have direct mappings, making it straightforward to pass them between the two. Here’s a quick reference:
Java Type | JNI Type | Size
byte | jbyte | 8 bits
boolean | jboolean | 8 bits (unsigned)
char | jchar | 16 bits (unsigned)
short | jshort | 16 bits
int | jint | 32 bits
long | jlong | 64 bits
float | jfloat | 32 bits
double | jdouble | 64 bits
void | void | N/A
These mappings allow direct conversion between Java and C types, simplifying the process when dealing with primitive data.
2. Passing Java Objects to C
When passing Java objects to C, you need to load the class and retrieve method IDs to interact with the object. For example, if a `Customer` object is passed from Java to C, and it has a method like `getName()`, the C code would look something like this:
JNIEXPORT jobject JNICALL Java_com_oracle_estt_sc_db_impl_SCQueryODBC__1getCustomer
(JNIEnv *env, jobject, jobject customer) {
jmethodID methodId;
jclass cls_objClass = env->GetObjectClass(customer);
methodId = env->GetMethodID(cls_objClass, "getName", "()Ljava/lang/String;");
jstring js_name = (jstring)env->CallObjectMethod(customer, methodId, NULL);
// ...
}
This allows C to call Java methods and retrieve values from Java objects.
3. Returning Java Objects from C to Java
To return a Java object from C, you first need to create an instance of the desired class, get the field IDs, set their values, and then return the object. For example, if you want to return a `Customer` object with a name attribute:
JNIEXPORT jobject JNICALL Java_com_oracle_estt_sc_db_impl_SCQueryODBC__1getCustomer
(JNIEnv *env, jobject, jobject customer) {
jclass clazz = env->FindClass("com/oracle/estt/sc/busi/Customer");
if (clazz == 0) return 0;
jobject obj = env->AllocObject(clazz);
jfieldID fid_id = env->GetFieldID(clazz, "customerID", "I");
jfieldID fid_name = env->GetFieldID(clazz, "name", "Ljava/lang/String;");
env->SetIntField(obj, fid_id, 1);
env->SetObjectField(obj, fid_name, jname);
return obj;
}
This approach ensures that the Java object is properly initialized and returned with the correct attributes.
4. Passing Arrays of Java Objects to C
When dealing with arrays of Java objects, such as an array of `Customer` objects, you need to iterate through the array, extract each object, and process its properties. For example:
JNIEXPORT void JNICALL Java_com_oracle_estt_sc_db_impl_SCInsertODBC__1insertCustomeRequest___3Lcom_oracle_estt_sc_busi_CustomerRequest_2
(JNIEnv *env, jobject, jobjectArray oa) {
jint size = env->GetArrayLength(oa);
for (int i = 0; i < size; i++) {
jobject o_customer = env->GetObjectArrayElement(oa, i);
// Process each customer object...
}
}
By looping through the array, you can extract each element, call its methods, or retrieve its fields, allowing flexible data handling between Java and C.
In summary, working with JNI requires careful handling of data types, object interactions, and memory management. Understanding how to pass and receive different types of data between Java and C is essential for building efficient and robust native extensions.
Solar tracker system,Fully automatic solar tracker,Solar tracker structure,Solar tracker bracket
Hebei Shuobiao New Energy Technology Co., Ltd. , https://www.pvbracketsystem.com