Java与C通过JNI指针相互传递

转载地址: http://blog.csdn.net/neo_86/article/details/24931509



注意

1、c中指针可以直接转为java里的int值,都是32位无损失(32位操作系统或者gcc 32编译器)。

2、循环里要注意释放本地引用,因为循环太多或不可预知,容易溢出,你没有做着咯额异常处理,jvm会直接退出,看不到打印堆栈信息的,所以使用jni时如果程序没有打印就无故退出,就检查下本地方法。

3、long 对应J不是L,会给出打印信息提示的(64位操作系统或gcc 64位)。


事例:

事例1、转成long(函数PtrToLong),它在java里是64位的,这个文件指针,我在java函数作用域是有效的,递归调用也可以,所以,不会被回收,需要手动关闭资源。

[cpp]  view plain  copy
  1. jlong Java_fang_android_OS_opendir(JNIEnv* env, jobject clazz, jstring jPath)  
  2. {  
  3.     __android_log_print(ANDROID_LOG_INFO,LOG_TAG, "");  
  4.     ScopedUtfChars path(env,jPath);  
  5.     //li(path);  
  6.   
  7.     DIR* d = NULL;  
  8.     d = opendir(path);  
  9.     __android_log_print(ANDROID_LOG_INFO,LOG_TAG,"sizeof(DIR*) = %d, %p"sizeof(DIR*), d);  
  10.     //li("sizeof(DIR*) = %d, %p", sizeof(DIR*), d);  
  11.     return PtrToLong(d);  
  12. }  



[cpp]  view plain  copy
  1. //readdir() 不是线程安全的,因为所返回的结构是存储在函数库中的一个静态变量。  
  2. //大多数现代的 UNIX 系统都具有线程安全的 readdir_r(),如果您正在编写线程代码,可以使用这个函数作为替代。  
  3. jstring Java_fang_android_OS_readdir(JNIEnv* pEnv, jobject clazz, jlong dir, jintArray fileinfo)  
  4. {  
  5.     dirent dirEntry, *entryPtr;  
  6.     int retval = readdir_r((DIR*)(long)dir, &dirEntry, &entryPtr);  
  7.     if (entryPtr == NULL || 0 != retval)  
  8.         return NULL;  
  9. //  dirent *pDirEntry = readdir((DIR*)(long)dir);  
  10. //  if (pEnv->ExceptionCheck()) {  
  11. //            return NULL;  
  12. //    }  
  13. //  if(NULL== pDirEntry){  
  14. //      return NULL;  
  15. //  }  
  16.     //li(pDirEntry->d_name);  
  17.     if(fileinfo != 0){  
  18.         jint* pFileInfo = (jint*)pEnv->GetPrimitiveArrayCritical(fileinfo, 0);  
  19.         if (pFileInfo)  
  20.         {  
  21.             int len = pEnv->GetArrayLength(fileinfo);  
  22.             if (len >= 4)  
  23.             {  
  24.                 pFileInfo[0] = dirEntry.d_ino;  
  25.                 pFileInfo[1] = dirEntry.d_off;  
  26.                 pFileInfo[2] = dirEntry.d_reclen;  
  27.                 pFileInfo[3] = dirEntry.d_type;  
  28.             }  
  29.             pEnv->ReleasePrimitiveArrayCritical(fileinfo, pFileInfo, 0);  
  30.         }  
  31.     }  
  32.     return pEnv->NewStringUTF(dirEntry.d_name);  
  33. }  


[cpp]  view plain  copy
  1. jint Java_fang_android_OS_closedir(JNIEnv* env, jobject clazz, jlong dir)  
  2. {  
  3.     int ret = closedir((DIR*)(long)dir);  
  4.     return static_cast(ret);  
  5. }  



事例2:

。还是官方代码,稍微转换一下,少依赖其他文件,这里ScopedLocalRef作用域完了会自动释放NewStringUTF的。

[cpp]  view plain  copy
  1. // Translate the intermediate form into a Java String[].  
  2. for (size_t i = 0; i < numEntries; ++i) {  
  3.     if (answer) {  
  4.         ScopedLocalRef localFileNameRef(pEnv, pEnv->NewStringUTF(currentEntry->pathEntry));  
  5.         //jstring jstrFileName = pEnv->NewStringUTF(currentEntry->pathEntry);  
  6.         if (pEnv->ExceptionCheck()) {  
  7.             return NULL;  
  8.         }  
  9.         //pEnv->SetObjectArrayElement(answer, i, jstrFileName);  
  10.         pEnv->SetObjectArrayElement(answer, i, localFileNameRef.get());  
  11.         if (pEnv->ExceptionCheck()) {  
  12.             return NULL;  
  13.         }  
  14.         //pEnv->DeleteLocalRef(jstrFileName);  
  15.     }  
  16.     free((void *) currentEntry);  
  17.     currentEntry = currentEntry->next;  
  18.     //pEnv->ReleaseStringUTFChars(s, currentEntry->pathEntry);  
  19.     //pEnv->DeleteLocalRef( s);  
  20. }  

事例3,注册本地函数时

[cpp]  view plain  copy
  1. {"opendir",     "(Ljava/lang/String;)J",                        (void*)Java_fang_android_OS_opendir},  
  2. {"closedir",    "(J)I",                                         (void*)Java_fang_android_OS_closedir},  
  3. {"readdir",     "(J[I)Ljava/lang/String;",                      (void*)Java_fang_android_OS_readdir},

你可能感兴趣的:(Java基础)