安卓开发 c java_Android NDK开发三:java和C\C++交互

1、定义native方法并加载动态链接库:

public class HelloJni extendsActivity

{

@Overridepublic voidonCreate(Bundle savedInstanceState)

{super.onCreate(savedInstanceState);

TextView tv= new TextView(this);

tv.setText( stringFromJNI() );

setContentView(tv);

}public native String stringFromJNI();

public nativeString unimplementedStringFromJNI();static {

System.loadLibrary("hello-jni");

}

}

2、实现native方法:

#include #includejstring

Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv*env,

jobject thiz )

{return (*env)->NewStringUTF(env, "Hello from JNI !"); //in c

returnenv->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、数据

原始数据类型:

0df995506bb3c3e1dac12de50f72cc17.png

引用数据类型:

8f012feaa3b792bf72466efb2f36353a.png

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 classJavaClass {/**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 classJavaClass {/*** Instance method.*/

privateString instanceMethod() {return "Instance Method";

}/*** Static method.*/

private staticString 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);

变量和函数的描述符:

1861beb7048f90cafab66164f0f0a121.png

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

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

8、处理异常:

public classJavaClass {/*** Throwing method.*/

private void throwingMethod() throwsNullPointerException {throw new NullPointerException("Null pointer");

}/*** Access methods native method.*/

private native voidaccessMethods();

}

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);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值