厂家的DLL函数的原型:char * GetErrMsgA(void);
int    GetMyID(char *myid);
我的思路是这样的:使用Swig,JNI对厂家的dll进行封装,然后用Vc 6.0编译产生Java可以直接使用的dll(Test.dll),最后在JAVA里调用厂家DLL里面的函数。当函数有Char * 类型的参数,遇到了问题JAVA中的代码:
          System.loadLibrary("Test"); //Test.dll就是新编译产生的dll
          
          String ErrMsg = "###";
          ErrMsg = Test.GetErrMsgA();
         System.out.println(ErrMsg);  //这个正常,可以打印出dll返回的ErrMsg数据
    
          String MyID = "***";
          Test.GetMyID(MyID);
          System.out.println(MyID); //这个地方就出问题了,一直打印的是"***";
    
    
现在可以肯定,已经成功调用厂家动态库里面的GetMyID函数,并且在厂家他们自己的日志里也能看到对应的记录和MyID,问题在于JAVA获取不到这个MyID,如何解决?
测试了其它dll里的函数,如果有参数是Char *类型,都有这个问题,如果函数返回值是Char *,那一切正常。刚开始使用JAVA,不是很熟,请指点

解决方案 »

  1.   

    这个涉及到传值的问题,思路就是java和C++访问同一块内存区域,你用Reference应该可以。
      

  2.   

    谢谢zxhcloth的回复,我感觉像是在是对不同的内存在做处理,所以java一直获取不到真正的数据。关于Reference能不能给个简单使用例子,谢谢
      

  3.   

    具体的我也记不清楚了(有快2年的时间没碰过它了),你自己多试试。
    java调用dll最棘手的就是回调部分,回调的原理就是操作同一块内存区。这个问题你摸透了,剩下的就都不是问题了。
      

  4.   


    现在卡在获取char *这块了,等这个弄完了后面也要用到回调的。因为char * GetErrMsgA(void);这个函数的返回数据用JAVA可以获取,我试着改写JNI代码,把int GetMyID(char *myid)里面的char *myid在JNI里面就直接返回给JAVA,而不是返回int,这样JAVA也是可以获取到myid数据的,但有两个缺点:
    1:JAVA里使用的函数结构和原型不一致 Test.GetMyID(MyID)变成返回String,而不是原来的int
    2:如果dll里有函数同时返回多个Char *,也比较麻烦。比如int GetInfo(char *myid,char * mySerial,char * logStr );其中myid,mySerial,logStr 都是dll要返回的数据
      

  5.   

    这个不应该是返回String类型么?jstring stoJstring(JNIEnv* env, const char* pat)
    {
    jclass strClass = env->FindClass("Ljava/lang/String;");
    jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
    jbyteArray bytes = env->NewByteArray(strlen(pat));
    env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);
    jstring encoding = env->NewStringUTF("utf-8");
    return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);
    }
    我学习JNI用的转换方法。看你有用么?
      

  6.   

    好吧。我没看清楼主的问题。你那个参数传递 可以用指针么?这个可以么?求教。个人觉得不应该是传String过去然后转换为char*的么?
      

  7.   

    好吧我有个问题 楼主代码看不懂啊?你为什么要
     String MyID = "***";
      Test.GetMyID(MyID);
      System.out.println(MyID); //这个地方就出问题了,一直打印的是"***";这样?
    你这方法有返回值,你打印MyID干嘛? 又没变化。我光想着自以为是你的问题去了。没注意你实际什么问题这个对么?
      

  8.   

    dll里的原型
    int GetMyID(char *myid);这个函数的功能是获取一个字符串,myid是存放这个字符串的首地址,整个函数的返回值是int类型,表示调用有没有成功,我是需要在java里面调用这个函数,获取到这个字符串ID
      

  9.   


    谢谢hwndid的回复,jni文档说明char *对应是jstring类型,在java里对应string。换成byte数组能具体说明一下吗
      

  10.   

    在调用接口中声明方法的返回类型为byte数组
      

  11.   

    我最近在学JNA,JNA比JNI好用些,你可以试一试
      

  12.   


    我是想尽量在java里保持本地方法的结构,因为方便其他人查看和调试。JNA我也测试过,也找到了解决这个char *类型传递的方法。但是因为本地dll里的方法很多,真的很多,还涉及到回调,数据结构等等数据类型,仅仅写几个函数结构描述问题不大,但要手动给每个本地方法写对应的JNA结构描述,这个是很费事的事情,而且还容易出错。我试着用JNAerator产生所有本地方法的JNA接口,但是导入JAVA后,调用本地方法一直不成功。在JNI环境下,是用swig自动生成所有本地方法的JNI代码,也可以在JAVA里调用成功,但是有这个参数传递的问题
      

  13.   

    java里面String是不可变的。所以把String传入再改变值是不允许的。
    jstring 是 jobject
    #define CHECK_EXCEPTION if((*env)->ExceptionCheck(env) == JNI_TRUE) returnint GetMyID(char *myid)
    {
        char* arr = "098abc";
        while (*arr)
        {
            *(myid++) = *(arr++);
        }
        *myid = 0;
    }JNIEXPORT jint JNICALL Java_JNITest_GetMyID
    (JNIEnv *env, jobject this, jobject buff)
    {
        JNIEnv _env = *env;
        jint len = _env->GetArrayLength(env, buff);
        CHECK_EXCEPTION 0;
        jbyte p[len];
        int r = GetMyID(p);
        if (!r)
        {
            _env->SetByteArrayRegion(env, buff, 0, len, p);
            CHECK_EXCEPTION 0;
        }
        return r;
    }
    public native int GetMyID(byte[] buff); public static void main(String[] args) throws Exception {
    JNITest t = new JNITest();
    byte[] buff = new byte[1000];
    if (t.GetMyID(buff) == 0) {
    String str = null;
    for (int i = 0; i < buff.length; i++) {
    if (buff[i] == 0) {
    str = new String(buff, 0, i);
    break;
    }
    }
    System.out.println(str);
    }
    }
      

  14.   

    对java不熟,原来String是不能变的,现在知道怎么回事了
    按照abc130314的回复,java 已经可以获取到 char*数据,谢谢
      

  15.   

    可以参考一下额以前写的博客
    http://blog.csdn.net/hemowolf/article/details/6924856
    http://blog.csdn.net/hemowolf/article/details/6925155
    http://blog.csdn.net/hemowolf/article/details/6925155虽然是在 linux 下的,但是原理没什么不一样