您的位置:首页 > 移动开发 > Android开发

Android NDK java和C\C++交互

2015-12-03 14:38 579 查看
1、定义native方法并加载动态链接库:



public class HelloJni extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);

TextView  tv = new TextView(this);
tv.setText( stringFromJNI() );
setContentView(tv);
}

public native String  stringFromJNI();

public native String  unimplementedStringFromJNI();

static {
System.loadLibrary("hello-jni");
}
}




2、实现native方法:



#include <string.h>
#include <jni.h>
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI !"); //in c
return env->NewStringUTF("Hello from JNI !");         //in c++

}




若要定义静态方法:

JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_stringFromJNI
(JNIEnv * env, jclass clazz);


头文件可以用javah工具生成:

进入命令行,切换到项目的bin目录下的classes下面,执行 javah -classpath . -jni 包.类名。

或者:cd 到src目录中,执行 javah 包.类名

3、数据

原始数据类型:



引用数据类型:



4、字符窜的操作:

1)新建字符串:

jstring javaString;

javaString = (*env)->NewStringUTF(env, "Hello World!");

2)把java string转换成c string



const jbyte* str;
jboolean isCopy;
str = (*env)->GetStringUTFChars(env, javaString, &isCopy);
if (0 != str) {
printf("Java string: %s", str);
if (JNI_TRUE == isCopy) {
printf("C string is a copy of the Java string.");} else {
printf("C string points to actual string.");}
(*env)->ReleaseStringUTFChars(env, javaString, str);




5、数组的操作:

1)新建java数组:

jintArray javaArray;
javaArray = (*env)->NewIntArray(env, 10);
if (0 != javaArray) {
/* You can now use the array. */}


2)获取数组的值:

jint nativeArray[10];
//将java array 复制到 c array
(*env)->GetIntArrayRegion(env, javaArray, 0, 10, nativeArray);
//将 c array 还原城 java array
(*env)->SetIntArrayRegion(env, javaArray, 0, 10, nativeArray);


获取数组指针:

jint* nativeDirectArray;
jboolean isCopy;
nativeDirectArray = (*env)->GetIntArrayElements(env, javaArray, &isCopy);
//...
(*env)->ReleaseIntArrayElements(env, javaArray, nativeDirectArray, 0);


6、C\C++获取java成员变量



public class JavaClass {
/** Instance field */
private String instanceField = "Instance Field";
/** Static field */
private static String staticField = "Static Field";
...}




1)获取Field ID

jclass clazz;
clazz = (*env)->GetObjectClass(env, instance);


jfieldID instanceFieldId;
instanceFieldId = (*env)->GetFieldID(env, clazz,
"instanceField", "Ljava/lang/String;");


jfieldID staticFieldId;
staticFieldId = (*env)->GetStaticFieldID(env, clazz,
"staticField", "Ljava/lang/String;");


2)获取Static Field

jstring staticField;
staticField = (*env)->GetStaticObjectField(env, clazz, staticFieldId);


7、C\C++调用java函数



public class JavaClass {
/**
* Instance method.
*/
private String instanceMethod() {
return "Instance Method";}
/**
* Static method.
*/
private static String staticMethod() {
return "Static Method";}
...}




1)获取Method ID:

成员函数:

jmethodID instanceMethodId;
instanceMethodId = (*env)->GetMethodID(env, clazz,
"instanceMethod", "()Ljava/lang/String;");


静态函数:

jmethodID staticMethodId;
staticMethodId = (*env)->GetStaticMethodID(env, clazz,
"staticMethod", "()Ljava/lang/String;");


2)调用:

jstring instanceMethodResult;
instanceMethodResult = (*env)->CallStringMethod(env,
instance, instanceMethodId);


变量和函数的描述符:



javap工具可以提取从编译过的class files 中提取这些描述符:

javap –classpath bin/classes –p –s com.example.hellojni.HelloJni

8、处理异常:



public class JavaClass {
/**
* Throwing method.
*/
private void throwingMethod() throws NullPointerException {
   throw new NullPointerException("Null pointer");}
/**
* Access methods native method.
*/
private native void accessMethods();}






jthrowable ex;
...
(*env)->CallVoidMethod(env, instance, throwingMethodId);
ex = (*env)->ExceptionOccurred(env);
if (0 != ex) {
(*env)->ExceptionClear(env);
/* Exception handler. */}




从c\c++抛异常:

jclass clazz;
...
clazz = (*env)->FindClass(env, "java/lang/NullPointerException");
if (0 ! = clazz) {
(*env)->ThrowNew(env, clazz, "Exception message.");}


9、本地和全局变量:

1)本地变量在函数结束时自动释放内存:

jclass clazz;
clazz = (*env)->FindClass(env, "java/lang/String");


2)新建全局变量:



jclass localClazz;
jclass globalClazz;
...
localClazz = (*env)->FindClass(env, "java/lang/String");
globalClazz = (*env)->NewGlobalRef(env, localClazz);
...
(*env)->DeleteLocalRef(env, localClazz);




3)释放全局变量:

(*env)->DeleteGlobalRef(env, globalClazz);


4)弱全局引用:

弱全局引用可以被内存自动回收:



jclass weakGlobalClazz;
weakGlobalClazz = (*env)->NewWeakGlobalRef(env, localClazz);
if (JNI_FALSE == (*env)->IsSameObject(env, weakGlobalClazz, NULL)) {
/* Object is still live and can be used. */} else {
/* Object is garbage collected and cannot be used. */}
(*env)->DeleteWeakGlobalRef(env, weakGlobalClazz);




10、线程:

synchronized(obj) {
/* Synchronized thread-safe code block. */}




if (JNI_OK == (*env)->MonitorEnter(env, obj)) {
/* Error handling. */}
/* Synchronized thread-safe code block. */
if (JNI_OK == (*env)->MonitorExit(env, obj)) {
/* Error handling. */}




native线程不能和java直接通信,必须先绑定到javaVM



JavaVM* cachedJvm;
...
JNIEnv* env;
...
/* Attach the current thread to virtual machine. */
(*cachedJvm)->AttachCurrentThread(cachedJvm, &env, NULL);
/* Thread can communicate with the Java application
using the JNIEnv interface. */
/* Detach the current thread from virtual machine. */
(*cachedJvm)->DetachCurrentThread(cachedJvm);


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: