锁定老帖子 主题:JNI学习记录
该帖已经被评为隐藏帖
|
|
---|---|
作者 | 正文 |
发表时间:2009-11-04
需要声明一下:本人是通过ITCast www.itcast.cn 的视频学习的。
1. JNI是Java与本地C/C++代码相互操作的一种方案。 2. 要使用JNI,需要: 1),在Java源程序中使用native关键字声明一个方法。 如: public native void callCppFunction(); 2),然后在命令行提示符下使用javah这个命令来生成关于JNI的本地头文件。 如: javah test.jni.MainArrayTest 3),在VC Studio中建立一个DLL工程,拷贝这个头文件到该工程目录下,拷贝 %JAVA_HOME%\include下面的jni.h、jni_md.h到工程目录下,或者加到系统目下,具体需要拷贝的头文件还要具体研究。 4),建一个cpp源文件,实现生成的头文件中声明的函数。 5),具体各种函数及数据类型的使用如下:具体自己研究:
l 简单方法调用,基本数据类型的使用 jclass clazz_TestNative = env->GetObjectClass(obj); /* jfieldID id_number = env->GetFieldID(clazz_TestNative, "number", "I"); jint number = env->GetIntField(obj, id_number);
cout<<number<<endl;
env->SetIntField(obj, id_number, 1000L); */
// jmethodID id_max = env->GetMethodID(clazz_TestNative, "max", "(DD)D"); // jdouble maxValue = env->CallDoubleMethod(obj, id_max, 3.14, 3.15);
// cout<<maxValue<<endl;
jfieldID id_person = env->GetFieldID(clazz_TestNative, "person", "Ltest/jni/Father;"); jobject person = env->GetObjectField(obj, id_person);
jclass clazz_Father = env->FindClass("test/jni/Father"); jmethodID id_Father_Function = env->GetMethodID(clazz_Father, "function", "()V"); env->CallVoidMethod(person, id_Father_Function); env->CallNonvirtualObjectMethod(person,clazz_Father, id_Father_Function);
l 对象的使用 jclass clazz_date = env->FindClass("java/util/Date"); jmethodID outputDate_ID = env->GetMethodID(clazz_date, "<init>", "()V");
jobject date_obj = env->NewObject(clazz_date, outputDate_ID); jmethodID mid_date_getTime = env->GetMethodID(clazz_date, "getTime", "()J");
unsigned times = env->CallLongMethod(date_obj, mid_date_getTime); // printf("%u",times); cout<<times<<endl; l 字符串的简单实用 jfieldID fid_msg = env->GetFieldID(env->GetObjectClass(obj), "message", "Ljava/lang/String;"); jstring j_msg = (jstring)env->GetObjectField(obj, fid_msg);
//const jchar *p_jst = env->GetStringChars(j_msg, NULL); //MessageBoxW(NULL,(const wchar_t *)p_jst, L"Title", MB_OK); jint len = env->GetStringLength(j_msg); jchar *j_buf = new jchar[len+1]; j_buf[len] = L'\0'; env->GetStringRegion(j_msg, 0, len, j_buf);
wstring wstr((const wchar_t *)j_buf); //env->ReleaseStringChars(j_msg, j_buf);//不能释放字符数组啊 delete []j_buf;
std::reverse(wstr.begin(), wstr.end()); jstring jnewStr = env->NewString((const jchar*)wstr.c_str(), wstr.size());
env->SetObjectField(obj, fid_msg, jnewStr);
l 数组的使用 jfieldID fid_arrays = env->GetFieldID(env->GetObjectClass(obj), "arrays", "[I"); jintArray jint_arr = (jintArray)env->GetObjectField(obj, fid_arrays);
jint *int_arr = env->GetIntArrayElements(jint_arr, NULL); jsize len = env->GetArrayLength(jint_arr);
for(int i = 0; i < len; ++i) { // cout<<int_arr[i]<<endl; } sort(int_arr, int_arr + len, less_second); env->ReleaseIntArrayElements(jint_arr, int_arr, /*JNI_ABORT/JNI_COMMIT/0*/0); }
bool less_second(const int & m1, const int & m2) { return m1 > m2; }
上面要注意在JNI中对Java中数据类型的映射,见头文件的声明。 还有注意Java中关于对象类型的表示方法比如:int I, boolean Z, Object L<类的完整名称,注意包名以/分隔>;,数组[<数据类型>。 如果不知道可以使用javap这个反编译器。
6)、更多资料,将Java手册。 7)、编译,生成DLL。将DLL的文件路径加到Path环境变量下: 8)、在Main函数中加载动态库。 如:System.loadLibrary("TestNative4"),注意不要DLL扩展名,为了跨平台嘛! 9)、如果使用的是eclipse之类的IDE工具,请重启,因为该类工具在启动时,默认读取了系统变量,但是不会监视变量的变化。 10)、注意在JNI中对Java对象的引用。不然垃圾回收将会产生问题。注意全局引用,局部引用、弱全局引用的使用。 局部引用,也就是本地方法中返回引用。应该使用DeleteLocalRef释放该引用。NewLocalRef创建。还用很多方式创建。 全局引用,需要手动释放,防止垃圾回收器回收。需要使用NewGlobalRef函数创建,释放它需要使用DeleteGlobalRef函数。 弱全局引用,需要编程人员手动释放,但是它不防止垃圾回收器的回收。 使用NewWeakGlobalRef创建,使用DeleteWeakGlobalref释放。IsSamObject(jobject obj1, jobject obj2)判断弱全局引用指向的对象是否已被回收。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
浏览 2486 次