注意
1、c中指针可以直接转为java里的int值,都是32位无损失。
2、循环里要注意释放本地引用,因为循环太多或不可预知,容易溢出,你没有做着咯额异常处理,jvm会直接退出,看不到打印堆栈信息的,所以使用jni时如果程序没有打印就无故退出,就检查下本地方法。
3、long 对应J不是L,会给出打印信息提示的。
事例:
事例1、转成long了,它在java里是64位的,这个文件指针,我在java函数作用域是有效的,递归调用也可以,所以,不会被回收,需要手动关闭资源。
jlong Java_fang_android_OS_opendir(JNIEnv* env, jobject clazz, jstring jPath)
{
__android_log_print(ANDROID_LOG_INFO,LOG_TAG, "");
ScopedUtfChars path(env,jPath);
//li(path);
DIR* d = NULL;
d = opendir(path);
__android_log_print(ANDROID_LOG_INFO,LOG_TAG,"sizeof(DIR*) = %d, %p", sizeof(DIR*), d);
//li("sizeof(DIR*) = %d, %p", sizeof(DIR*), d);
return PtrToLong(d);
}
//readdir() 不是线程安全的,因为所返回的结构是存储在函数库中的一个静态变量。
//大多数现代的 UNIX 系统都具有线程安全的 readdir_r(),如果您正在编写线程代码,可以使用这个函数作为替代。
jstring Java_fang_android_OS_readdir(JNIEnv* pEnv, jobject clazz, jlong dir, jintArray fileinfo)
{
dirent dirEntry, *entryPtr;
int retval = readdir_r((DIR*)(long)dir, &dirEntry, &entryPtr);
if (entryPtr == NULL || 0 != retval)
return NULL;
// dirent *pDirEntry = readdir((DIR*)(long)dir);
// if (pEnv->ExceptionCheck()) {
// return NULL;
// }
// if(NULL== pDirEntry){
// return NULL;
// }
//li(pDirEntry->d_name);
if(fileinfo != 0){
jint* pFileInfo = (jint*)pEnv->GetPrimitiveArrayCritical(fileinfo, 0);
if (pFileInfo)
{
int len = pEnv->GetArrayLength(fileinfo);
if (len >= 4)
{
pFileInfo[0] = dirEntry.d_ino;
pFileInfo[1] = dirEntry.d_off;
pFileInfo[2] = dirEntry.d_reclen;
pFileInfo[3] = dirEntry.d_type;
}
pEnv->ReleasePrimitiveArrayCritical(fileinfo, pFileInfo, 0);
}
}
return pEnv->NewStringUTF(dirEntry.d_name);
}
jint Java_fang_android_OS_closedir(JNIEnv* env, jobject clazz, jlong dir)
{
int ret = closedir((DIR*)(long)dir);
return static_cast<jint>(ret);
}
。还是官方代码,稍微转换一下,少依赖其他文件,这里ScopedLocalRef作用域完了会自动释放NewStringUTF的。
// Translate the intermediate form into a Java String[].
for (size_t i = 0; i < numEntries; ++i) {
if (answer) {
ScopedLocalRef<jstring> localFileNameRef(pEnv, pEnv->NewStringUTF(currentEntry->pathEntry));
//jstring jstrFileName = pEnv->NewStringUTF(currentEntry->pathEntry);
if (pEnv->ExceptionCheck()) {
return NULL;
}
//pEnv->SetObjectArrayElement(answer, i, jstrFileName);
pEnv->SetObjectArrayElement(answer, i, localFileNameRef.get());
if (pEnv->ExceptionCheck()) {
return NULL;
}
//pEnv->DeleteLocalRef(jstrFileName);
}
free((void *) currentEntry);
currentEntry = currentEntry->next;
//pEnv->ReleaseStringUTFChars(s, currentEntry->pathEntry);
//pEnv->DeleteLocalRef( s);
}
事例3,注册本地函数时
{"opendir", "(Ljava/lang/String;)J", (void*)Java_fang_android_OS_opendir},
{"closedir", "(J)I", (void*)Java_fang_android_OS_closedir},
{"readdir", "(J[I)Ljava/lang/String;", (void*)Java_fang_android_OS_readdir},