androidNDK开发之JNI学习
1、在工程目录下编译
1
| javah -classpath F:\eclipse\adt-bundle-windows-x86-201309017\sdk\platforms\android-19\android.jar;bin/classes com.example.jnithread.MainActivity
|
2、增加log信息的方法
在.c文件中添加
1 2 3 4 5
| #define LOG_TAG "System.out.cpp" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
|
在配置mk文件增加
1 2 3
| #liblog.so libGLESv2.so LOCAL_LDLIBS += -llog
|
e.g
3、类型转换
4、对象传递机制
假如类为c/c++类,并开始在c/c++程序建立:
返回对象以jlong 类型强制转换对象的指针值,从而将c/c++的对象返回到java中以long变量保存起来,以便后续工作回调c/c++中的对象。
e.g
1 2 3 4 5 6 7 8 9
| dataInCpp * data1=new dataIntCpp(); return (jlong)data1; jlong data1; dataInCpp * data2 = (dataInCpp *)data1;
|
假如类为java类,通过c/c++程序创建
A、在c++中创建并返回给java程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| Jclass clazz = env->FindClass(“com/example/jnithread/myData”); If(!clazz){ return NULL; } jmethodID constr = env->GetMethodID(clazz,”<init>”,”()V”); if(!constr){ return; } jobject newObj = env->NewObject(clazz,constr); if(!newObj){ return; } return newObj;
|
在java程序中直接用类型myData接收即可,无需用Object
B、将c++中创建的java对象再传回给c++方法
1
| jclass clazz = env->GetObjectClass(dataObject);
|
接下来和调用java类中函数一样如下所述
5、简单说明一下c++调用java函数:
非静态方法调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| jclass dpclazz = env->FindClass(”com/example/jnithreads/MainActivity”); if(dpclazz==0){ LOGI(“find class error”); return; } jmethod method1 = env->GetMethodID(dpclazz,”getNum”,(参数)V); If(method1==0){ LOGI(“find method1 error”); Return; } env->CallVoidMethod(obj,method1);
|
注:
1/返回类型定义
2/如果要调用类似【”hello”.getBytes(“gb2312”);】则需要
1
| env->CallVoidMethod(obj,”hello”,method1,”gb2312”);
|
3/ byteArray->char *
1 2 3 4 5 6 7 8 9
| jsize len = env->GetArrayLength(byteArray); jbyte* ba = env->GetByteArrayElements(byteArray,JNI_FALSE); if(len>0){ char * rtn = (char *)malloc(len+1); memcpy(rtn,ba,len); rth[len]=0; } env->ReleaseByteArrayElements(byteArray,ba,0); return rtn;
|
4/获取java对象的ID为:
1 2
| jfieldID field_a=env->GetFieldID(dpclazz,”a”,”I”); int ma=(int)env->GetObjectField(obj,field_a);
|
静态方法调用:
获取非静态方法的ID:
1
| jmethod methodID = env->GetStaticMethodID(dpclazz,”getNum”,(参数)V);
|
调用静态方法:
1
| env->CallStaticVoidMethod(dpclazz,mthodID,参数)
|
熟记:get 参数 clazz call参数 obj,methodID
如果是static的话,call前面obj改为clazz
6、全局变量
Jobject的子类别包括jclass、jstring,、jarray(这些类称为局部性的对象参考),他们就算定义成static,也要利用函数:
1
| gObj = env->NewGlobalRef(obj);将其赋值从而保持全局性
|
7、JNI线程模式的调用
8、利用C++回调来更新UI(Handler)
同步锁:(java调用c++)
1、定义的时候:
1
| private native synchronized String execute(Object oSync);
|
进入函数资源调用时:
1
| env->MonitorEnter(syncObj);
|
释放时:
1
| env->MonitorExit(syncObj);
|
上面讲的是不同线程情况下将对象传入C++程序,所以还是与线程安全有关
如果是在c++程序中的多线程,也一样。
多线程注意:
1 2 3 4 5
| if (0 == gVm->AttachCurrentThread(&env, NULL)) { gVm->DetachCurrentThread(); …… }
|