JNA传递byte数组给C函数出现乱码及长度异常问题求助
故障原因
C语言的字符串依赖末尾的\0(空终止符)判断结束边界:
- 你直接传递Java的
byte[]时,String.getBytes()生成的数组只包含字符串本身的字节内容,没有额外追加空终止符 - C侧的
strlen、printf("%s")都会持续读取内存直到遇到\0才停止,超出原byte数组的部分就是随机内存数据,所以会出现乱码、长度统计错误 - 直接传String类型正常是因为JNA底层会自动给String参数追加空终止符后再传给C函数,但String对应的内存是不可修改的,所以不符合你的改写需求
可行解决方案
方案1:手动给byte数组追加空终止符(最常用)
在Java侧构造byte数组时,多分配1位长度留作空终止符即可,Java数组初始化时默认填充0,刚好对应C的\0:
/* load library*/ libPGM=loadLibrary(); // user defined function to load C library String str = "Abcdefg"; // 显式指定字符集避免跨环境乱码 byte[] strBytes = str.getBytes(java.nio.charset.StandardCharsets.UTF_8); // 构造带空终止符的数组 byte[] byteArr = new byte[strBytes.length + 1]; System.arraycopy(strBytes, 0, byteArr, 0, strBytes.length); System.out.println("byte length is :"+strBytes.length); String str_2=new String(strBytes, java.nio.charset.StandardCharsets.UTF_8); System.out.println("Inside the java pgm "+str_2); libPGM.foo(byteArr);
注意:如果你的C程序需要修改字符串内容,并且修改后的长度比原字符串长,需要根据实际业务场景提前给byte数组分配足够的长度,避免内存越界。
方案2:给C函数增加长度参数(更安全)
修改C函数额外接收一个长度参数,避免依赖空终止符判断边界,适合未知输入内容的场景:
void foo(unsigned char * inp, int len){ setbuf(stdout, NULL); // 用指定长度打印字符串 printf("data received is %.*s\n", len, inp); printf("The size is %d \n", len); // 改写内容时也以len作为边界判断,避免越界 }
Java侧调用时直接传原byte数组和数组长度即可:
libPGM.foo(byteArr, byteArr.length);
内容的提问来源于stack exchange,提问作者Alok Ranjan Swain
相关产品推荐
相关产品推荐

