I am developing an application for android in eclipse and now I have a problem and I need your help. So I must Call function written in C from JAVA application. But on my way of writing code I have some Questions which you can see below. I am waiting for your answers and ideas ...
typdef struct blobData_s {
unsigned long length;
unsigned char data[1];
} blobData_t;
unsigned int CheckEnrollmentExist ( unsigned long hdevice, blobData_t* pInputInfo ) {
// Function code goes here
..........................
return some_value;
}
In JAVA code instead of unsigned long
I use int
so I can write.
class jblobData_c {
public int langth;
*Question 1.*
}
public class ApplicationMainClass extends Activity {
// Some code goes here
......................
public native int JCheckEnrollmentExist( int jhdevive, *Question 2.* );
}
Question 1.
unsigned char
in JAVA Code ?unsigned char data[1];
?Question 2.
class jblobData_c
instead of blobData_t* pInputInfo
in the JAVA Code ?blobData_t* pInputInfo
?JNIEXPORT jint JNICALL Java_com_Test_JCheckEnrollmentExist(JNIEnv* env, jobject obj, jint jhdevice, *Question 2.* ) {
// Call the base function from C code.
return CheckEnrollmentExist( jhdevice, *Question 3.*);
}
Question 3.
CheckEnrollmentExist
function that is C Code Function instead of blobData_t* pInputInfo
in order this function works right and given parameter be the sameIn short, JNIEXPORT contains any compiler directives required to ensure that the given function is exported properly. On android (and other linux-based systems), that'll be empty. JNICALL contains any compiler directives required to ensure that the given function is treated with the proper calling convention.
JNI = Java Native Interface. Native = platform dependent. JNI is optional and very specialized part of Java, you are not forced to use it for any of your Java coding. JNI is meant to be used for isolated tasks which absolutely cannot be done in JVM.
Introduction to Java Native Interface: Establishing a bridge between Java and C/C++ JNI (Java Native Interface) is a foreign function interface that allows code running on JVM to call (or be called by) native applications. Using JNI, one can call methods written in C/C++ or even access assembly language.
For question #1:
You can use a jchar. Primitive chars in java are not signed, it's about the only primitive that isn't. Note that jchar is a UTF-16 char, so you will have to "map" the jchar to a regular char, as you would have to with any character conversion issue. For simple conversions, this can typically be done by casting
char c_char = (char)java_char;
because the core ASCII shares the same numeric values between ASCII and UTF-16. However, this is prone to error should anyone actually attempt to pass a "special" character through the interface. A much better way would be to (in the java side, as it is easier) convert the characters to bytes using the appropriate character set for your platform (to ensure platform compatibility in the C layers). Then you only need to pass a byte[] to the JNI call, and the bytes will correctly correspond to the characters that C likely will expect.
For question #2:
If your CheckEnrollmentExists(...)
method is the JNI binding entry point, you cannot change data types safely. That means that all entry inputs must be JNI data type values. While you might be able to select the C data type equivalents (and you might be able to get your compiler to do it anyway) such techniques should be frowned upon. This implicitly means that JNI entry points cannot accept struct data structure not defined in the JNI headers. In other words, you can't pass your own struct to the method.
If the method needs access to a C struct across calls, use another means. I've seen people store the pointer to the allocated data structure in a member integer or long (doing correct casting). You can then rewrite the native code side to retrieve the pointer from the "this" object being passed into the call, and the do a dereference to obtain the required data.
For Question #3:
This is actually the same as question #2. In the "binding wrapper" you put, you would retrieve the pointer's stored value in the java object's int or long field, cast it to the appropriate struct pointer and then pass it to the internal method. As the passing of the pointer is a C to C call, no extra magic is required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With