2013-01-19 35 views
1

对不起,在对象中可能看起来有点通用,但我没有与Android NDK开发经验,我试图将Java方法转换为本机代码,我遇到一些问题。Android NDK,JNI代码不工作和相关的疑惑

最初的Java代码不是我的,而是取自一个开源库。

我有这样的感觉,我正在做一些与内存有关的错误以及处理对象的方式。

i_out是和从Java传入并在其中我从本地方法中设置一些值的对象。

这是在Android Java代码中定义的方法签名:

private native int nativeXLineToRle(int i_x, int i_y, int i_len, int i_th, NyARLabeling_Rle.RleElement[] i_out, byte[] buffer, int width); 

这是精细地与NDK建造编译的代码:

#include <jni.h> 

JNIEXPORT jint JNICALL Java_jp_androidgroup_nyartoolkit_utils_NyARRlePixelDriverYUV420Reader_nativeXLineToRle(JNIEnv * env, jint i_x, jint i_y, jint i_len, jint i_th, jobjectArray i_out, jbyteArray buffer, jint width) 
{ 
     int       current = 0; 
     int       r = -1; 

     int       st = i_x + width*i_y; 
     int       x = st; 
     int       right_edge = st + i_len - 1; 

     jobject      anRleElement = (*env)->GetObjectArrayElement(env, i_out, 0); 
     jclass      rleElementClass = (*env)->GetObjectClass(env, anRleElement); 

     jfieldID     lFid = (*env)->GetFieldID(env, rleElementClass, "l", "I"); 
     jfieldID     rFid = (*env)->GetFieldID(env, rleElementClass, "r", "I"); 

     jobject      currentRleElement; 

     jbyte*      buf = buffer; 

     while (x < right_edge) { 
      if (buf[x] > i_th) { 
       x++; 
       continue; 
      } 

      r = (x - st); 

      currentRleElement = (*env)->GetObjectArrayElement(env, i_out, current); 

      (*env)->SetIntField(env, currentRleElement, lFid, r); 

      r++; 
      x++; 
      while (x < right_edge) { 
       if (buf[x] > i_th) { 
        (*env)->SetIntField(env, currentRleElement, rFid, r); 

        current++; 
        x++; 
        r = -1; 
        break; 
       } else { 
        r++; 
        x++; 
       } 
      } 
     } 

     currentRleElement = (*env)->GetObjectArrayElement(env, i_out, current); 

     if (buf[x] > i_th) { 
      if (r >= 0) { 
       (*env)->SetIntField(env, currentRleElement, rFid, r); 
       current++; 
       currentRleElement = (*env)->GetObjectArrayElement(env, i_out, current); 
      } 
     } else { 
      if (r >= 0) { 
       (*env)->SetIntField(env, currentRleElement, rFid, r+1); 
      } else { 
       (*env)->SetIntField(env, currentRleElement, lFid, i_len-1); 
       (*env)->SetIntField(env, currentRleElement, rFid, i_len); 
      } 
      current++; 
     } 
     return current; 
} 

的Android 2.3运行代码.3设备logcat显示以下内容:

"Signal Catcher" daemon prio=5 tid=4 RUNNABLE 
    | group="system" sCount=0 dsCount=0 obj=0x4050d430 self=0x119b78 
    | sysTid=2343 nice=0 sched=0/0 cgrp=default handle=2511112 
    at dalvik.system.NativeStart.run(Native Method) 
"GLThread" prio=5 tid=12 RUNNABLE 
    | group="main" sCount=1 dsCount=0 obj=0x40532180 self=0x2b7c20 
    | sysTid=2356 nice=0 sched=0/0 cgrp=default handle=2850136 
    at jp.androidgroup.nyartoolkit.utils.NyARRlePixelDriverYUV420Reader.nativeXLineToRle(Native Method) 
    at jp.androidgroup.nyartoolkit.utils.NyARRlePixelDriverYUV420Reader.xLineToRle(NyARAndYUV420GsRaster.java:268) 
    .............. 
    at com.badlogic.gdx.backends.android.surfaceview.GLSurfaceViewCupcake$GLThread.run(GLSurfaceViewCupcake.java:646) 

而一个的Android 4.1.2设备上我得到如下:

E/dalvikvm(3443): JNI ERROR (app bug): accessed stale weak global reference 0x7f (index 31 in a table of size 0) 
E/dalvikvm(3443): VM aborting 
A/libc(3443): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1), thread 3544 (Thread-36107) 

现在我很卡住所以任何帮助将是非常赞赏。 在此先感谢

弗朗西斯

回答

0

线21是错误的。 jbyteArray是一个对象,一个不能转换它到jbyte *。您应该使用一个JNI函数:

(*env)->ReleaseByteArrayElements(env, buffer, buf, JNI_ABORT); 

jbyte* buf = (*env)->GetByteArrayElements(env, buffer, NULL); 

数组应前回报发布