I have created my first native call in Java with the Android SDK today.
I found a few examples but there aren't consistent with the function head.I used always
JNIEXPORT void JNICALL Java_com_test_Calculator_calcFileSha1
(JNIEnv *, jclass, jstring);
but I have seen
JNIEXPORT void JNICALL Java_com_test_Calculator_calcFileSha1
(JNIEnv *, jobject, jstring);
Belonging to the heads are different was to get the class of the caller.
But what is the preferred way?From the C++ code I want to call a java method. I found the JNI documentation (Calling Instance Methods).
But I don't know what the first parameter (object) should be.I tried to give the class instance which I get from the call of the native method, which fails with an AbstractMethodError.
Fixed source code:
public class TestCalc extends Activity {
static {
System.loadLibrary("Test");
}
private void setFilesize(long size) {
}
}
Native Library:
// header
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_com_test_TestCalc_calcFilesize
(JNIEnv *, jobject, jstring);
void setFilesize(const INT_64 size);
#ifdef __cplusplus
}
#endif
#endif
// code
JNIEnv * callEnv;
jobject callObj;
JNIEXPORT void JNICALL Java_com_test_SHA1Calc_calcFileSha1
(JNIEnv * env, jobject jobj, jstring file)
{
callEnv = env;
callObj = jobj;
[...]
}
void setFilesize(const INT_64 size) {
jmethodID mid;
jclass cls;
cls=callEnv->FindClass("com/test/TestCalc");
mid=callEnv->GetMethodID(cls, "setFilesize", "(J)V");
if (mid == 0) {
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:LC: [%s]", "Cannot find method setFilesize");
return;
}
callEnv->ExceptionClear();
callEnv->CallVoidMethod(callObj, mid, size);
if(callEnv->ExceptionOccurred()) {
callEnv->ExceptionDescribe();
callEnv->ExceptionClear();
}
}
Thanks for any advices.
Call[type]Method is only for private methods and constructors. (Calling Instance Methods) When you call a public method, you will get an AbstractMethodError.
jobject
could be any java object while jclass
is supposed to be an object representing java.lang.Class
. In C API, jobject
and jclass
is the same thing while C++ API is trying to enforce type safety and declares those as different types where jclass
inherits jobject
. The second argument is supposed to represent a class, so jclass
is preferred. Even if in C it doesn't matter, it can hint the developer or even save you time if you ever decide to switch to C++. Read more about JNI types here.
精彩评论