这是我网上查到的用jni去调用dll的简单例子,但是感觉逻辑有点乱
明明是java去调用dll,现在反过来又用java生成一个dll了,然后再去调用1) 编写java程序:这里以HelloWorld为例。
  代码1: 
  class HelloWorld { 
  public native void displayHelloWorld();
  static { 
  System.loadLibrary("hello");                             //要调用的dll库
  } 
  public static void main(String[] args) { 
  new HelloWorld().displayHelloWorld(); 
  }
  } 
2) 编译 javac HelloWorld.java 生成HelloWorld.class文件
3) 生成扩展名为h的头文件 javah HelloWorld 生成HelloWorld.h的头文件4) 编写本地方法实现和由javah命令生成的头文件里面声明的方法名相同的方法。
  代码2: 
  1 #include "jni.h"
  2 #include "HelloWorld.h"
  3 //#include other headers 
  4 JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj) 
  {
  printf("Hello world!\n");
  return;
  }                                                              //用C++实现
  5) 生成动态库
  这里以在Windows中为例,需要生成dll文件。在保存HelloWorldImpl.c文件夹下面,使用VC的编译器cl成。 cl -I%java_home%\include -I%java_home%\include\win32 -LD HelloWorldImp.c -Fehello.dll 注意:生成的dll文件名在选项-Fe后面配置,这里是hello,因为在HelloWorld.java文件中我们loadLibary的时候使用的名字是hello。当然这里修改之后那里也需要修改。另外需要将-I%java_home%\include -I%java_home%\include\win32参数加上,因为在第四步里面编写本地方法的时候引入了jni.h文件。                             //又生成dll文件,这个就是前面加载的那个dll库文件吧
  6) 运行程序 java HelloWorld就ok.所以有点乱,明明在HelloWorld.java中System.loadLibrary("hello")加载了,可是后面又通过javac,javah等操作生成个hello.dll,所以看到迷糊了,请教大侠指点迷津还有就是c++,c,c#编写的dll文件一样么,用java调用的方法是一样的么                           

解决方案 »

  1.   

    1 dll 是规范的
    2 生成dll 无所谓了,java也可以调用编译器的,你把功能分开,一个就负责使用,一个就负责生成,各自调试。
      

  2.   

    LZ把顺序反过来思考就行了,
    首先应该要有hello.dll,
    然后才能有System.loadLibrary("hello"),没有dll又哪来的加载呢,对吧 **
    但这其中涉及到jni,所以
    首先把主类写好,于是就先有System.loadLibrary("hello")
    然后调用javah生成相应的头文件,然后实现该头文件中声明的方法,该方法就是主类的native void displayHelloWorld()方法的具体实现,主类并没有实现displayHelloWorld()方法对不对?
    主类并没有实现displayHelloWorld()方法,要调用它必然是通过外部的连接库,那么主类是如果定位这个连接库呢,就是System.loadLibrary("hello"),上面**的地方也说了,要先有dll才有加载,所以就有LZ的第五步
    5) 生成动态库dll是win系统的规范,所以没什么太大的差别,java要调用它必须要用jni,即整个过程大同小异
      

  3.   

    还是没大明白专家的意思,
    明明是我调用dll,现在怎么反过来我又生成一个dll啊
    这两个dll是不是一个dll啊
    正常不是先有dll,然后我们再写java代码去调用它的么,现在怎么又要我们去写个本地方法,再编译,再有c++去实现,再生成dll呢
    真的感觉晕了
      

  4.   

    3楼的说得很清楚了,你要反过来想就对了。
    不是你生成一个dll,是你的需求需要你调用一个dll,那个dll是本来就有的,而且相应的一套东西也应该是
    全的。你只负责写你那个主类就可以了。
      

  5.   

    谢谢你详细的解释,不过我还是有点迷惑,在4)中还是要自己去实现头文件里面的方法,如果dll不是我们写的,我们又怎么会知道里面的具体实现呢,正常我们去调用给的现场的dll,现在却反过来要我们自己去实现,不是很矛盾么
      

  6.   

    明明是java去调用dll,现在反过来又用java生成一个dll了,然后再去调用这个看实现的人的喜好,因为既存dll接口都已经定好了,所以主类就不能native void displayHelloWorld()这样随意定义接口了
    一般来说,主类并不直接调用既存的dll,因为dll的接口类型,参数类型有可能跟java不一样,所以都是自己定义一个接口,即自己做一个dll,然后在这个dll去调用其它的dll
      

  7.   

    既然先有的hello.dll,可是这个hello.dll不是从HelloWorld.java这个类一步一步编译成的么
    到底是先有鸡还是先有蛋呢,我很笨,请您指点迷津啊
      

  8.   

    在我的这个例子中,有中间的dll么
    还有要自己做一个dll,那么是不是还要懂c++/c啊?因为我不会在dll里再调dll
      

  9.   

    你的例子没有中间dll
    代码2: 
      1 #include "jni.h" 
      2 #include "HelloWorld.h" 
      3 //#include other headers 
      4 JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj) 
      { 
      printf("Hello world!\n"); 
      return; 
      }                   
    这段代码就是c代码
    win系统的调用dll,有动态调用和静态调用
    动态调用使用loadLibrary,即在上面的代码中loadLibrary(xxx.dll);然后通过函数指针指向dll的接口而调用
    静态就是通过#include把dll或lib导入,跟java的import类似
      

  10.   

    既然没有中间的dll,我们要调用hello.dll,就说明这个dll是先给出来的,然后我们来调用,但是现在的hello.dll还是我们用java生成的
      

  11.   

    我说的中间dll是指你没有通过中间dll调用hello.dll,这个hello.dll是你自己生成的,你可以在你的hello.dll里去调用别的dll,怎么调用上面已经说了
    你要直接调用dll,那你就要知道该dll的接口在java中的定义形式
    即native void displayHelloWorld(); 改成dll的接口在java中的定义形式
    我上班用不了QQ,不好意思
      

  12.   

    msn可以么,[email protected]
    现在的实际问题是这样的,给我一个dll的文件,让我去用java调用
    dll的名字:test.dll
    里面的方法名:temp()
    返回值是String类型的
    我应该怎么做
    剩下的什么都没有了
      

  13.   

    如果在4)中去调用别的dll,那生成的这个dll是不是就是充当中间dll的角色了
      

  14.   

    理论上确实是这样的,上面说了dll是win系统的规范,形式大同小异,但dll的接口可以各式各样,
    而jni是java的规范,要求dll的接口要符合jni规范
    你从别人那里拿到的test.dll,如果接口本身符合jni规范,那你可以直接调用
    如果不符合,那就只能生成个中间dll去调用如果你的test.dll符合jni规范,那直接声明public native String temp(); 然后System.loadlibry("test.dll");即可
    如果不符合jni规范
    那就修改例子的代码中调用你的test.dll
    public native void displayHelloWorld(); 改成
    public native String getTemp(); 1 #include "jni.h" 
      2 #include "HelloWorld.h" 
      3 //#include other headers 
        #include "test.h" //如果有头文件或者有lib,可以直接导入,如果是lib,要声明一下temp接口
      4 JNIEXPORT jstring JNICALL Java_HelloWorld_getTemp(JNIEnv *env, jobject obj) 
      { 
          return temp(); //如果有头文件的话 
      }   如果没有头文件或lib
    #include <windows.h> //here
    4 JNIEXPORT jstring JNICALL Java_HelloWorld_getTemp(JNIEnv *env, jobject obj) 
      { 
           HMODULE hDllLib = LoadLibrary(_T("test.dll")); 
           jstring rtn;
           if (hDllLib)
          {
              FARPROC fpTemp = GetProcAddress(hDllLib,"temp");
              rtn = (*fpTemp)();
              FreeLibrary(hDllLib);
          }      return rtn;
      }