JNI char*转jstring乱码问题

绝世酱油瓶 2013-01-19 02:06:09
JNIEXPORT jstring JNICALL Java_com_szzc_jni_JniApi_getCardSerial
(JNIEnv * env, jobject obj, jcharArray js){
hModule=LoadLibrary("OUR_MIFARE.dll");
gcnum = (getCardNum)GetProcAddress(hModule, "piccrequest");
//.....
unsigned char * str = (unsigned char *)env->GetCharArrayElements(js,NULL);
unsigned char cardNum = gcnum(str);
printf("卡列号:\n");
unsigned char* p = str;
while(*p!='\0'){
printf("%x\n",*p);
p++;
}
//定义java String类 strClass
jclass strClass = env->FindClass("Ljava/lang/String;");
//获取java String类方法String(byte[],String)的构造器,用于将本地byte[]数组转换为一个新String
jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
//建立byte数组
jbyteArray bytes = env->NewByteArray((jsize)strlen((const char *)str));
//将char* 转换为byte数组
env->SetByteArrayRegion(bytes, 0, (jsize)strlen((const char *)str), (jbyte*)(const char *)str);
//设置String, 保存语言类型,用于byte数组转换至String时的参数
jstring encoding = env->NewStringUTF("utf-8");
//将byte数组转换为java String,并输出
jstring status = (jstring)env->NewObject(strClass, ctorID, bytes, encoding);
cout << status <<endl;
return status;
// return (jstring)cardNum;
}

我需要将str的值返回给java端、while循环打印出来的结果是:1a a7 de d4这个是正确的结果、
我经过转jstring的操作之后、就过就不对了、而且一直变化、java端收到也是乱码、这个该怎么处理?或者以什么形式返回、急啊、希望大牛们能自己编写一个测试的dll测试过了给个解决办法?

---------------------------------------------下面是我补充刚做的测试:
	unsigned char  devicenumber[4];
devicenumber[0]=7;
devicenumber[1]=111;
devicenumber[2]=218;
devicenumber[3]=64;
jstring deviceNum = env->NewStringUTF((const char*)devicenumber);
return deviceNum;

C端直接写死、
			s = new JniApi().getDeviceNo(test);
System.out.println(s);
String str = new String(s.getBytes("UTF-8"));
System.out.println(str);

java打印的都是乱码、
C端如果这样写、写成字符串、
unsigned cahr * test="1A2B3C4D";
都不会乱码。、这个倒底怎么回事?没人知道吗
...全文
856 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
BadPattern 2013-01-21
  • 打赏
  • 举报
回复
一个个来说,首先你的native函数有误: unsigned char devicenumber[4] = {7,111,218,64}; jstring deviceNum = env->NewStringUTF((const char*)devicenumber); return deviceNum; C/C++的字符串必须以\0结尾,所以你这里应该修改为const char devicenumber[5] ={7,111,218,64,'\0'};否则产生的字符串会有问题! -------------------------------------- 其次你的java端测试方法有误: System.out.println(str); 这个str由7,111,218,64这几个字符组成,在ascii码中: 7代表响铃符 111代表小写字母o 218不在ascii内 64代表@符 所以这样打印会显示:oÚ@ 所以这样打印是不对的!要这样打印: for(int i = 0 ; i < str.length(); i++){ System.out.println((int)str.charAt(i)); } 你要分清啥是人类可阅读的字符好不。。。
dracularking 2013-01-19
  • 打赏
  • 举报
回复
unsigned char devicenumber[4]; devicenumber[0]=7; devicenumber[1]=111; devicenumber[2]=218; devicenumber[3]=64; jstring deviceNum = env->NewStringUTF((const char*)devicenumber); return deviceNum; 如果这样导致乱码,是编解码不一致导致,先搞清楚c这边是怎么编码的 查看下deviceNum的值来推测 不妨参考下这个例子 // Prompt user for a C-string char outCStr[128]; printf("Enter a String: "); scanf("%s", outCStr); // not more than 127 characters // Step 3: Convert the C-string (char*) into JNI String (jstring) and return return (*env)->NewStringUTF(env, outCStr);
为啥呢 2013-01-19
  • 打赏
  • 举报
回复
引用 4 楼 lib739449500 的回复:
jna中要使用char *必须用CharByReference类型
不要鹦鹉学舌....
xlhb 2013-01-19
  • 打赏
  • 举报
回复
jna中要使用char *必须用CharByReference类型
为啥呢 2013-01-19
  • 打赏
  • 举报
回复
jna中要使用char *必须用CharByReference类型
绝世酱油瓶 2013-01-19
  • 打赏
  • 举报
回复
引用 1 楼 leandzgc 的回复:
推荐楼主用JNA技术来用java调用C或C++写的DLL,我前段时间也遇到了用java调用C++写的dll的问题,我是直接没写成,总是报错,N种错。最后用JNA解决了,貌似到现在一直没出问题,几个月了。
JNA可以返回char *吗?我上次试了一下、有问题、我本来就不懂C、你帮我看看是啥问题。或者给我提供下那种demo。网上查的都没返回值什么的、因为如果要用JNA、我需要去改动现存的DLL的源码。我不太会、
 unsigned char *  __stdcall pcdgetdevicenumber(unsigned char *devicenumber)
{
//	AfxMessageBox("hello",NULL,NULL);
//	memcpy((char *)devicenumber,"\x7\x6f\xda\x40\x00\x00",6);
///*
	devicenumber[0]=7;
	devicenumber[1]=111;
	devicenumber[2]=218;
	devicenumber[3]=64;
	devicenumber[4]=0;

//	*/

//	unsigned char sn[20],cRet;
//	cRet=ReadSN(sn);
//	if(!cRet)two_one(sn+5,8,devicenumber);
	return devicenumber;

}
这个原型原本是返回char、return 0;被我改成了char *、我的java代码:
public class TestDll {
	public interface CLibrary extends StdCallLibrary {
		CLibrary INSTANCE = (CLibrary) Native.loadLibrary("OUR_MIFARE",
				CLibrary.class);

		public String pcdgetdevicenumber(String value);

	}

	public static void main(String[] args) {
		String value="1";
		String b = CLibrary.INSTANCE.pcdgetdevicenumber(value);
		System.out.println(b+"-"+value);

	}

}
为什么我输出的是“INI~1\AppData\Local\Temp-1”这种玩意。、?
leandzgc 2013-01-19
  • 打赏
  • 举报
回复
推荐楼主用JNA技术来用java调用C或C++写的DLL,我前段时间也遇到了用java调用C++写的dll的问题,我是直接没写成,总是报错,N种错。最后用JNA解决了,貌似到现在一直没出问题,几个月了。

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧