2013-02-28 169 views
5

我在这里遇到了一个很大的问题。我试图从Java传递一个byte []到C++,并且在转换后我得到负值。我已经确定了Java字节[]中具有唯一字符的问题,该字符在转换并执行日志后,值为0或负值。将JNI Java byte []转换为C++ bytearray,返回0

我已经尝试使用字符串测试字节[],它工作正常。

这是我的代码,如果有帮助。

爪哇

public static native void SendMessage(byte[] message, int size); //size = message.length 

C++

static void SendMessage(JNIEnv *env, jclass cls, jbyteArray array, jint array_length) 
{ 
    jbyte* content_array = (env)->GetByteArrayElements(array,NULL); 
    //*env->GetByteArrayRegion(array,0,array_length,content_array); //tried this as well, same results 
    LOGD("content:\n"); 
    for (int i=0; i < array_length; i++) 
    { 
     LOGD("%d",content_array[i]); 
    } 

    //EDIT 
    SendMessage(client, (uint8_t*)content_array, array_length); //<- could the problem be at the point where I convert it to uint8_t? 

     (env)->ReleaseByteArrayElements(array,content_array,0); 
    } 

输出

content: 48 
content: 23 
content: 13 
content: 56 
content: 0 // <--- the problem starts here 
content: -122 
content: 0 
content: 78 
content: 32 
content: -28 
etc... 
.. 
.. 

现在,使用一个简单的测试字节[] 爪哇

String test = "ABC"; 
byte[] message = test.getBytes(); 
public static native void SendMessage(byte[] message, int size); //size = message.length 

C++

static void SendMessage(JNIEnv *env, jclass cls, jbyteArray array, jint array_length) 
{ 
    jbyte* content_array = (env)->GetByteArrayElements(array,NULL); 
    //*env->GetByteArrayRegion(array,0,array_length,content_array); //tried this as well, same results 
    LOGD("content:\n"); 
    for (int i=0; i < array_length; i++) 
    { 
     LOGD("%d",content_array[i]); 
     } 
     (env)->ReleaseByteArrayElements(array,content_array,0); 
    } 

输出

content: 65 //this works perfectly 
content: 66 
content: 67 

感谢您的帮助。非常感激。

回答

1

你是如何获得问题案例中的byte[]数组?那也是从String转换而来吗?如果是这样,在日志输出中获得零和负值可能是完全有效的。它取决于您用来转换为字节数组的输入字符和编码。如果您使用String.getBytes()与简单文本一样,则将使用平台默认编码。你的简单案例表明默认编码是ASCII兼容的。

+0

感谢您的回复。不,我没有从字符串转换中获取字节[]。字节[]从另一个来源传递。为了记录目的,我能够将它转换为Java端的String,并且看到它包含唯一的字符。 你提到过不同的编码。如何从平台默认设置不同的编码? – user2117849 2013-02-28 03:27:23

+0

使用[String.getBytes(Charset)](http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#getBytes(java.nio.charset.Charset))。 – 2013-02-28 03:30:08

1

我不确定你认为问题在这里。在Java中,byte是签名类型,所以负值不是意外。 Jbyte大概是一个匹配的8位有符号C++类型。

最有可能的解释是:

  • 这是你创建的字节数组的方式有些假象;例如您在UTF-8编码的(虽然零往往会以其他方式来表示......)

  • 你已经得到了size参数不正确的值:

    • 出于某种原因,它更大比字节数组大小。

    • 将东西写入字节数组的过程未将size字节放入其中。


值得注意的是,你的JNI代码不检查0 <= size < message.length。如果使用size参数调用此方法超出范围,则可能发生坏事......包括分段错误,这将导致硬件JVM崩溃。

+0

谢谢斯蒂芬的回复,不,我做了一个检查,以确保大小是正确的。但是,我没有在我的文章(自编辑)中提到我已经将转换后的数组转换为uint8_t。难道这就是接收端只能读取消息直到0的问题吗? uint8_t是否支持0和负值? – user2117849 2013-02-28 05:28:53

+0

'uint8_t'的取值范围为0到255.然而,由于这是一个C/C++类型转换,因此您会*告诉代码将数组中的值视为无符号数。无论如何,基于更新,我认为这个问题不在您向我们展示的代码中。 – 2013-02-28 06:06:55