java调用dll文件的几种常见方式

java调用动态库需要关注的问题:

   1. 如何装载DLL文件,以及如何定位所要使用的方法;

   2. 数据类型如何对应;

   3. 如何给使用的方法传递参数;

   4. 如何获取返回的值。

一. 数据类型对应关系

   Java Type        C Type
    boolean
        int
    byte
       char
   char
      wchar_t
   short
      short
    double
      double
    float
      float
   String
      char*

二. Jnative调用dll

   Jnative是对JNI技术进行了封装,更加方便的让java去调用DLL。

     1. 下载Jnative库,其中包含JNative.jar, JNativeCPP.dll, JNativeCPP.so这三个包。 JNative.jar是需要导入到Java工程的lib下, JNativeCPP.dll文件放在jdk安装目录下,或者是user\System32目录下,或者项目根目录下。

     2. 将需要调用的dll动态链接库放在SYSTEM32文件夹下,或者是项目根目录下,否则会出现找不到dll文件的错误。

     3. 加载DLL库 : System.loadLibrary("TranferEth");  // TransferEth为需要调用的DLL文件,只需要使用DLL文件的文件名即可。

     4. 调用DLL入口函数 : JNative jnt = new JNative("TransferEth.dll", "Transfer_Ethernet");  // 参数1为需要调用的DLL文件, 参数2为需要调用的方法。

     5. 设置返回参数类型 : jnt.setVal(Type.INT);

     6. 设置传入参数 : jnt.setParameter(0, "TransferScale.ini");

     7. 执行调用 : jnt.invoke();

     8. 释放资源 : jnt.dispose();

三. JNA调用dll

  

JJNA中,它提供了一个动态的C语言编写的转发器,可以自动实现Java和C的数据类型映射。你不再需要编写C动态链接库。
  
 1.  在java项目中引入jna.jar。 (当前引用的版本为3.4.0 , 之前的版本未提供释放动态链接库资源的方法)
 2.  定义调用接口, 接口方法与需要调用的DLL提供的外部函数一致。
     例如 : DLL文件中提供入口函数:

     extern "C" __declspec(dllexport) UINT __stdcall Transfer_Ethernet_EX(char *cTransScale , int nKey);

     extern "C" __declspec(dllexport) UINT __stdcall Transfer_Ethernet(char *cTransScale );

则定义的接口类中如下:  (数据类型对应关系如上)

public interface CallMTScaleLibrary extends Library {
  
    public int Transfer_Ethernet_EX(String filename, int key);  
   
    public int Transfer_Ethernet(String filename); 
}

 3.  加载DLL文件

String dir = path + "dllName";  // dll文件的路径,可以省略后缀名,dll和so后缀都可以加载

CallMTScaleLibrary scaleLibrary =  (CallMTScaleLibrary) Native.loadLibrary(dir, CallMTScaleLibrary.class);

4. 执行调用

  int result = scaleLibrary.Transfer_Ethernet(path + "TransferScale.ini");

5. 释放资源

   一次调用完成后需要释放掉资源,以便后续重复调用该资源。通过查看jna的源码Native类中有私有方法dispose()可以主动释放掉资源,可以通过反射的方式去调用该方法,也可以重写该方法,从而实现释放。

private static void  dispose(){
           NativeLibrary.disposeAll();         
           nativeLibraryPath = null;
}

  注意问题 :  1. 文件路径: DLL文件最好放在项目的根目录下,或者是system32文件夹下,必须在环境变量配置的path中。
                 2. 循环调用: 当循环调用同一个DLL文件时,必须要释放掉上一次的资源,否则会被占用端口(每次调用都会在线程里进行一次网络通讯)。

你可能感兴趣的:(Java)