我现在需要用java去调用现存的DLL里的几个函数。
函数原型如下“unsigned char __stdcall piccrequest(unsigned char *serial)
unsigned char __stdcall piccreadex(unsigned char ctrlword,unsigned char *serial,unsigned char area,unsigned char keyA1B0,unsigned char *picckey,unsigned char *piccdata0_2)
下面是我JNI的声明:
/**
 * @param serial
 * @return返回卡序列號
 */
public native String getCardSerial(char[] serial); /**
 * @return讀取0~2塊數據
 */
public native String getCardData(char ctrlWord, char[] serial, char area,
char key, char[] picckey, char[] piccdata0_2);对应的C端的代码:
typedef    unsigned char  (__stdcall * getCardNum)(unsigned char[]);
typedef    unsigned char  (__stdcall * getDeviceNum)(unsigned char[]);
typedef    unsigned char  (__stdcall * getCardData)(unsigned char,unsigned char[],unsigned char,unsigned char,unsigned char[],unsigned char[]);
HINSTANCE hModule=NULL;
getCardNum gcnum;
getDeviceNum gdnum;
getCardData gdata;/*
读取卡序列号
*/
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("the return value of func is %d\n",cardNum); 
printf("卡列号:\n");
unsigned char* p = str;
while(*p!='\0'){
    printf("%x\n",*p);
    p++;
}
return (jstring)cardNum;
}JNIEXPORT jstring JNICALL Java_com_szzc_jni_JniApi_getCardData
(JNIEnv * env, jobject obj, jchar jc, jcharArray ja1, jchar jc2, jchar jc3, jcharArray ja2, jcharArray ja3){
hModule=LoadLibrary("OUR_MIFARE.dll"); 
gdata = (getCardData)GetProcAddress(hModule, "piccreadex");
unsigned char ctrlWord = (unsigned char)jc;
unsigned char area = (unsigned char)jc2;
unsigned char key=(unsigned char)jc3;
unsigned char * serial= (unsigned char *)env->GetCharArrayElements(ja1,NULL);
unsigned char * picckey= (unsigned char *)env->GetCharArrayElements(ja2,NULL);
unsigned char * piccdata= (unsigned char *)env->GetCharArrayElements(ja3,NULL);
unsigned char status = gdata(ctrlWord,serial,area,key,picckey,piccdata);
printf("%d\n",status);
cout << jc << endl;
cout << jc2 <<endl;
cout<< jc3 <<endl;
cout << "****" <<endl;
unsigned char* p = serial;
while(*p!='\0'){
    printf("%x\n",*p);
    p++;

jstring j=(jstring)"test";
return j;
}
我想问的是、在getCardSerial这个函数里面。怎么把str返回到java端、我java端传过去的是一个空的。调用DLL后才有的值、因为我getCardData这个函数还需要这个str结果。然后char ctrlWord = 0x01 + 0x02 + 0x04 + 0x08 + 0x10;
char[] serial = { 0x1a, 0xa7, 0xde, 0xd4 };
char area = 0;
char key = 1;
char[] picckey = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
char[] piccdata0_2 = new char[64];
new JniApi().getCardData(ctrlWord, serial, area, key, picckey,
piccdata0_2);
对于char数组、以及单个的char、这样的声明方式是不是有问题?
因为我在C端打印serial 这个。好像只打印了第一个元素"1a"出来了。

解决方案 »

  1.   

    c++中调试能得到这个返回的cardNum值吗?还有jstring这种返回类型正确吗 就是与java的String契合吗
      

  2.   

    封装一个对象返回吧,印象里JNI应当是不支持引用返回数据的
      

  3.   

    cardNum、str都能打印出来。结果正确、我需要的是str最返回到java端、无论以什么形式返回、
      

  4.   


    你说在C++端打印serial 这个。好像只打印了第一个元素"1a"出来了。 如果传进去时是一个数组包含n个元素(n>1),在c++端调试却查到只有一个,这肯定是有问题的关键现在是不是做的整合调试?通过jni去调用,以确定c++端方法确实被调用了,这样就差不多剩下类型匹配的问题了。
      

  5.   

    这些打印当然都是在java端调用的时候打印的了、那个打印一个的、但是我打印长度是4个、我传进去的也是4、执行函数获得的结果也是正确的、可能是这样处理char有点问题。、我换成byte之后正常了、我现在急的是、如何把str能返回到java端、不知道怎么处理这个、因为我其他函数需要这个函数的结果。我对VC++这端不熟悉。、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("the return value of func is %d\n",cardNum); 
    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;
    }我也试过转成string、那样最后的结果又不正确、
      

  6.   

    可能不是这样转,按照这个例子看下呢
    #include <jni.h>
    #include <stdio.h>
    #include "TestJNIString.h"
     
    JNIEXPORT jstring JNICALL Java_TestJNIString_sayHello(JNIEnv *env, jobject thisObj, jstring inJNIStr) {
       // Step 1: Convert the JNI String (jstring) into C-String (char*)
       const char *inCStr = (*env)->GetStringUTFChars(env, inJNIStr, NULL);
       if (NULL == inCSt) return NULL;
     
       // Step 2: Perform its intended operations
       printf("In C, the received string is: %s\n", inCStr);
       (*env)->ReleaseStringUTFChars(env, inJNIStr, inCStr);  // release resources
     
       // 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);
    }
    重点 4.2  Passing Strings
    http://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html
      

  7.   

    你说的这种我也试过、我不知道为什么一样还是乱码、
    我C里并没有、我对C不熟悉、NewStringUTF这个不就是在new一个UTF编码的jstring吗?
    我在java端转码了一样乱码