Upload
kentpon-wang
View
211
Download
0
Embed Size (px)
Citation preview
JNI 使用淺談 阿胖 2016.09.29
Android Taipei
Outline1. Java call c
2. c call java
3. c vs cpp
4. Data Type Mapping
5. Data Type Convert
6. JNIEnv
Java call c
HelloJni.java
hello-jni.c
HelloJni.java
public native String stringFromJNI();
static {
System.loadLibrary("hello-jni");
}
hello-jni.c
jtype Java_PATH_NAME_CLASSNAME_FUNCTIONNAME(
JNIEnv* env, jobject thiz [,… jparams] )
hello-jni.c
jstringJava_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ){ char msg[] = "Hello World from JNI !"; jstring jMsg = (*env)->NewStringUTF(env, msg);
return jMsg;}
c call java
HelloJni.java
hello-jni.c
HelloJni.java
private void callFromJni(String msg) {
Log.i(TAG,"123 "+msg);
}
hello-jni.cNativeType Call<type>Method(JNIEnv *env, jobject obj, jmethodID methodID, ...);NativeType Call<type>MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);NativeType Call<type>MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
jclass GetObjectClass(JNIEnv *env, jobject obj);
hello-jni.cpp
jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ) { char msg[] = "Hello World from JNI !"; jstring jMsg = env->NewStringUTF(msg);
return jMsg;}
jclass jClass = env->GetObjectClass(thiz); jmethodID mid = env->GetMethodID(jClass, "callFromJni", "(Ljava/lang/String;)V" ); env->CallVoidMethod(thiz, mid, jMsg);
c vs cpp
jstring jMsg = (*env)->NewStringUTF(env, msg);
jstring jMsg = env->NewStringUTF(msg);
#ifdef __cplusplusextern "C" {#endif
#ifdef __cplusplus}#endif
Data Type Mapping
Java primitive data type Native primitive data type Description
void void None
byte jbyte 8-bit signed. Range is -2^7 to 2^7 - 1
int jint 32-bit signed. Range is -2^31 to 2^31 - 1
float jfloat 32 bits. Represent a real number as small as 1.4 x 10-45 and as big as 3.4 x 1038 (approx.), positive or negative
double jdouble 64 bits. Represent a real number as small as 4.9 x 10-324 and as big as 1.7 x 10308 (approx.), positive or negative
char jchar 16-bit unsigned. Range is 0 to 65535
long jlong 64-bit signed. Range -2^63 to 2^63 - 1
short jshort 16-bit signed. Range is -2^15 to 2^15 - 1
boolean jboolean Unsigned 8 bits. true and false
Data Type Mapping
Java Reference type JNI type Description
java.lang.object jobject Any Java object
java.lang.String jstring String representation
java.lang.Class jclass Java class object
java.lang.Throwable jthrowable Java throwable object
Data Type MappingType Signature Java TypeZ boolean
B byte
C char
S short
I int
J long
F float
D double
V void
[ []
L<packet>/object; object
Data Type Mapping
Function in java signature
int foo() “()I”
void foo(byte[] arg) “([B)V”
boolean foo(String arg) “(Ljava/lang/String;)Z”
"(parameterFieldDescriptor)returnFieldDescriptor"
Data Type Convert
NewStringUTFjstring NewStringUTF(JNIEnv *env, const char *bytes);jstring jstr = (*env)->NewStringUTF(env, "This comes from jni.");
GetStringUTFCharsconst char * GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy);const char* str = (*env)->GetStringUTFChars(env, jstr , NULL);
ReleaseStringUTFCharsvoid ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf);
String
Data Type Convert
New<PrimitiveType>Array RoutinesArrayType New<PrimitiveType>Array(JNIEnv *env, jsize length);
Set<PrimitiveType>ArrayRegion Routinesvoid Set<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array,jsize start, jsize len, const NativeType *buf);
Array
Data Type Convert
Get<PrimitiveType>ArrayElements RoutinesNativeType *Get<PrimitiveType>ArrayElements(JNIEnv *env,ArrayType array, jboolean *isCopy);
Release<PrimitiveType>ArrayElements Routinesvoid Release<PrimitiveType>ArrayElements(JNIEnv *env,ArrayType array, NativeType *elems, jint mode);
Get<PrimitiveType>ArrayRegion Routinesvoid Get<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array,jsize start, jsize len, NativeType *buf);
Array
Data Type Convert
struct{ char name[256]; int num;} Foo;
Object
class Foo { public String name; public int num;}
Data Type Convert
FindClassjclass FindClass(JNIEnv *env, const char *name);“your/java/path/name/class_name$inner_class_name”
jmethodID mid = env->GetMethodID(msgClass, "<init>", "()V" );
NewObjectjobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
GetFieldIDjfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
Set<type>Field Routinesvoid Set<type>Field(JNIEnv *env, jobject obj, jfieldID fieldID, NativeType value);
Get<type>Field RoutinesNativeType Get<type>Field(JNIEnv *env, jobject obj, jfieldID fieldID);
Object
Data Type Convert
NewGlobalRefjobject NewGlobalRef(JNIEnv *env, jobject obj);
DeleteGlobalRefvoid DeleteGlobalRef(JNIEnv *env, jobject globalRef);
DeleteLocalRefvoid DeleteLocalRef(JNIEnv *env, jobject localRef);
static_cast<type>
JNIEnv
jint JNI_OnLoad(JavaVM* vm, void* reserved){ LOGI("JNI_OnLoad"); JNIEnv* env = NULL; jint result = -1; if(vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) { return result; }
jvm = vm; return JNI_VERSION_1_4;}
JNIEnv* getJNIEnv() { JNIEnv* env = NULL; int res = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
if (res == JNI_EDETACHED) { //LOGI("GetEnv: not attached"); if (jvm->AttachCurrentThread(&env, NULL) != 0) { LOGI("Failed to attach"); return NULL; } } else if (res == JNI_OK) { // } else if (res == JNI_EVERSION) { LOGI("GetEnv: version not supported"); return NULL; } return env;}
JNIEnv
JNIEnv* env = getJNIEnv();
/* do something */
jvm->DetachCurrentThread();
Reference
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html
http://www.developer.com/java/data/jni-data-type-mapping-to-cc.html
source code : https://github.com/kentpon/hello-jni
QA