unsigned char __stdcall piccrequest(unsigned char *serial)
{
unsigned char cRet;
unsigned char pnsr[6]; cRet=checkM1();
if(cRet)return 24; cRet=M1Request(0x0A,pnsr);
if(cRet)return 8;
cRet=M1Select(pnsr);
if(cRet)return 10;
if(serial==NULL)return 0;
else memcpy(serial,pnsr,4);
return 0;}
这是现存的VC编写的DLL里面的一个函数、我需要通过JNI去实现它。我java的声明如下:
public native short getCardSerialNum(short[] serial);
对应实现VC如下:typedef   unsigned char  (* getCardNum)(unsigned char[]);
HINSTANCE hModule=NULL;
getCardNum gnum;
JNIEXPORT jshort JNICALL Java_com_szzc_jni_JniApi_getCardSerialNum
(JNIEnv * env, jobject obj, jshortArray js){
hModule=LoadLibrary("OUR_MIFARE.dll"); 
gnum = (getCardNum)GetProcAddress(hModule, "piccrequest");
//.....
char * str = (char *)env->GetShortArrayElements(js,NULL);}注释往后不会处理了、谁可以完善下。我不知道java端申明的数据类型、VC端函数指针的申明等是否正确。给出正确的可以加分

解决方案 »

  1.   

    char对应的类型,你用byte就可以了。都是一个字节
    public native byte getCardSerialNum(byte[] serial);
    JNIEXPORT jbyte JNICALL Java_dll_1test_Main_getCardSerialNum
    (JNIEnv *env, jobject this, jbyteArray buff)
    {
        JNIEnv _env = *env;
        jbyte *serial = _env->GetByteArrayElements(env, buff, NULL);
        char r = piccrequest(serial);
        _env->ReleaseByteArrayElements(env, buff, serial, 0);
        return r;
    }
      

  2.   

    typedef   unsigned char  (* getCardNum)(unsigned char[]);HINSTANCE hModule=NULL;getCardNum gnum;
    这些怎么处理?我这里还需要调用现存的DLL里面的函数的
      

  3.   

    我unsigned char  (* getCardNum)(unsigned char[]);这个声明正确?
      

  4.   

    问题还没解决吗
    我又查了下,你这里java native方法参数还是不要用byte[] serial,改用char[] serial
    然后:typedef   unsigned char  (* getCardNum)(unsigned char[]);
    HINSTANCE hModule=NULL;
    getCardNum gnum;
    JNIEXPORT jshort JNICALL Java_com_szzc_jni_JniApi_getCardSerialNum
    (JNIEnv * env, jobject obj, jcharArray js){
        hModule=LoadLibrary("OUR_MIFARE.dll"); 
        gnum = (getCardNum)GetProcAddress(hModule, "piccrequest");
        //.....
        unsigned char * str = (unsigned char *)env->GetCharArrayElements(js,NULL);
        //然后直接调用dll中的函数
        unsigned char cardNum = gnum(str);
        //打印一下,查看函数有没有调用成功
        printf("the return value of func is %c\n",cardNum);
    }
        
      

  5.   

    是啊。天天被催的看不进去了、
    --------------------Configuration: mifareCard - Win32 Debug--------------------
    Compiling...
    mifareCard.cpp
    F:\Microsoft Visual Studio\MyProjects\mifareCard\mifareCard.cpp(40) : error C2556: 'short __stdcall Java_com_szzc_jni_JniApi_getCardSerialNo(struct JNIEnv_ *,class _jobject *,class _jcharArray *)' : overloaded function differs only by return type fr
    om 'unsigned short __stdcall Java_com_szzc_jni_JniApi_getCardSerialNo(struct JNIEnv_ *,class _jobject *,class _jcharArray *)'
            f:\microsoft visual studio\myprojects\mifarecard\com_szzc_jni_jniapi.h(32) : see declaration of 'Java_com_szzc_jni_JniApi_getCardSerialNo'
    F:\Microsoft Visual Studio\MyProjects\mifareCard\mifareCard.cpp(40) : error C2371: 'Java_com_szzc_jni_JniApi_getCardSerialNo' : redefinition; different basic types
            f:\microsoft visual studio\myprojects\mifarecard\com_szzc_jni_jniapi.h(32) : see declaration of 'Java_com_szzc_jni_JniApi_getCardSerialNo'
    Error executing cl.exe.mifareCard.obj - 2 error(s), 0 warning(s)
    报错啊、怎么提示重载错了?我头文件就只有一个函数了啊 我把其它的全删掉了
      

  6.   


    Java_com_szzc_jni_JniApi_getCardSerialNo函数重复定义了,检查一下你的代码,上面的意思是如果两个函数只是返回类型不同不能算重载。如果jni下面的native代码都要你写,那你就得抽空学学c++了,公司难道没有懂的人么,问问呢
      

  7.   

    就我一个做软件。唉 我也想问。我换了个函数名、编译好了。但是java端调用有问题。原型unsigned char __stdcall piccrequest(unsigned char *serial)
    函数指针申明是不是要加上stdcall ?The value of ESP was not properly saved across a  function call.
    This is usually a result of calling a function declared  with one calling 
    convention with a function pointer declared with a different calling convertion.
    (Press Retry to debug the application)
      

  8.   

    java端调用有啥问题啊,描述清楚一点。__stdcall是微软搞的东西,函数调用约定,win32 API一般都加上这个修饰,自己写的函数未必需要,没怎么搞过windows下的开发,要不要加,你自己测试一下不就好了。
      

  9.   

    typedef    unsigned char  (__stdcall * getCardNum)(unsigned char[]);
    这样写好了。但是问题一个接着一个。头疼。打印的乱码、我再把char换成其它类型试试
      

  10.   

    哦,那就不要%c打印,乱码因为char的取值不在ASC码范围之内
    改成:
     printf("the return value of func is %d\n",cardNum);
      

  11.   

    最后请教下、。unsigned char __stdcall piccrequest(unsigned char *serial)我这个原型函数呢。返回0表示成功了。、然后我把 str也打印了一下、   printf("the return value of func is %d\n",str);printf("the return value of func is %d\n",cardNum); 因为我需要的是str那个值、the return value of func is 179445344
    the return value of func is 0
    返回的结果是这样过的、“179445344”这个东西转换成16进制、好像又与我实际的结果不符合。 char[] test = new char[5];
    // new JniApi().getNumber(test);
    new JniApi().getDeviceNum(test);java里面这样调用有问题吗?函数原型传入的参数不需要赋值的。只用分配4个char空间的可写数组
      

  12.   

    char长度给4返回的是the return value of func is 179457632
      

  13.   

    str是字符指针,你也用%d去打,是打出了该指针指向的字符地址,179445344你打印出来的是地址值的十进制表示啊要打印出str每个字符的16进制表示,用:
    unsigned char* p = str;
    while(*p!='\0'){
       printf("%x\n",*p);
       p++;
    }
      

  14.   

    我这个str怎么返回啊我这里虽然能打印出来。但是我需要在java端取值、 jstring rtstr = env->NewStringUTF((const char *)str);
    return rtstr;我这么返回去的是乱码
      

  15.   


    你这都打印出乱码了,java端不是已经获取到了。
    要能打印出可以供人阅读的字符串,必须每个字节都在ASCII范围内,再说你这里字符串不并是为了给人阅读用的,是函数调用用的。
    如果只是为了调试用,就打印出字符串每个字节的16进制值好了。
      

  16.   

    如果返回到java端的是乱码。我再在java端调用的话那也没用吧、而且我这里也需要把这个str显示在页面上给用户看、 unsigned char* p = str;
    while(*p!='\0'){
        printf("%x\n",*p);
        p++;
    } 就像这种打印一样。没法把这个16进制结果拼接成字符串传递回去吗?
      

  17.   

    大哥,str是你java端传递过去的,你又要native层再将它传递给java打印,有必要么
      

  18.   

    这个。。我在12楼描述了。我从java端传递过去的其实是空的。、因为这个函数的原型只需要分配几个长度的char数组就可以返回数据了、所以我才需要返回的结果。