zoukankan      html  css  js  c++  java
  • 【转载】java调用C++写的DLL

    用java调用C++写的DLL一直以来都是一个比较麻烦但又很常见的问题。

    我们知道,使用 JNI 调用 .dll/.so 共享类库是非常非常麻烦和痛苦的。

    如果有一个现有的 .dll/.so 文件,如果使用 JNI 技术调用,我们首先需要另外使用 C 语言写一个 .dll/.so 共享库,使用 SUN 规定的数据结构替代 C 语言的数据结构,调用已有的   dll/so 中公布的函数。然后再在 Java 中载入这个适配器 dll/so ,再编写 Java   native 函数作为 dll 中函数的代理。经过 2 个繁琐的步骤才能在 Java 中调用本地代码。因此,很少有 Java 程序员愿意编写调用 dll/.so 库中的原生函数的 java 程序。这也使 Java 语言在客户端上乏善可陈。可以说 JNI 是 Java 的一大弱点。

    现在好了出现了一个JNA的武器,JNA框架是一个开源的 Java 框架,是 SUN 公司主导开发的,建立在经典的 JNI 的基础之上的一个框架。通过JNA能够很方便的调用C++写的DLL。

    先来一个Hello Word

    C++代码

     #ifndef DEMOC_H
     #define DEMOC_H
     #ifndef DLLDIR
     #define DLLDIR  extern "C"__declspec(dllexport)
     #endif
     typedef struct{
           char *m_sername;                   
           char *m_username;                 
           char *m_password;      
           WORD m_tranType;    
           HWND m_hChMsgWnd;  
           UINT m_nChmsgid;    
           int  m_sockType;       
           int  m_errormsg;  
           void (WINAPI *m_messagecallback)(LONG hHandle,char *wParam,int lParam);
           void *context;         
     }SERVER_UPDATEINFO;
     DLLDIR LONG __stdcall VSNET_ServerStart(char *m_url,SERVER_UPDATEINFO *m_pSerinfo,WORD wserport = 3000);
     #endif

    这是一个标准的C++头文件,在这个头文件中定义了一个函数VSNET_ServerStart,下面来分析一下这个头文件。首先看到在这个头文件中定义了一个宏DLLDIR,这个宏意义为导出编码为标准C(extern "C"),并且为declspec的。

    然后看到在头文件中还定义了一个结构体SERVER_UPDATEINFO,在SERVER_UPDATEINFO中具有以下几种数据类型:char类型指针,word类型,hwnd类型,uint,int,回调函数,void指针。

    这就是我们知道DLL中的所有信息。

    对了还有一个比较关键的地方,在C、C++中如果直接编译DLL,在DLL中导出的函数名是会在编译时被编译器修改掉,所以我们必须制定导出的函数名,这就需要在工程中定义一个def文件。

    def文件

     LIBRARY    "demoC"
     EXPORTS
     VSNET_ServerStart

    好了到此为止这就是我们所知道的所有DLL信息,一般这也是DLL组件会暴漏出来的所有信息。下面就来说明用JNA如何调用。

    首先我们先把DLL中的函数导出来,编程JAVA 的代码

     public interface CLibrary extends StdCallLibrary {
         VSNET_ServerStart
     }

    声明一个CLibrary的java接口,继承自JNA类库中的StdCallLibrary。OK已经导出来了,对了就这么简单。

    那么有些同学就问了,这个函数在C++的头文件中有一个LONG的返回值,而且还有参数啊?别急下面就来讲解。

    首先我们看到VSNET_ServerStart有一个LONG的返回值,LONG是C++中的数据类型,在java中是没有的,但是JNA已经为我们提供了这种类型叫做NativeLong。OK那么修改一下我们的JAVA代码

     public interface CLibrary extends StdCallLibrary {
         NativeLong VSNET_ServerStart
     }

    下面是JNA类型与C++类型的对比:

    接下来我们来看函数的参数如何处理。

    VSNET_ServerStart函数的参数为(char *m_url,SERVER_UPDATEINFO *m_pSerinfo,WORD wserport = 3000)。通过类型的对比我们知道char *=String,WORD=short。那个SERVER_UPDATEINFO这种结构体如何处理呢。

    在JNA中类库提供了一种Structure的类型专门处理结构体。下面我们用JAVA来描述一下这个结构体。

     public static class SERVER_UPDATEINFO extends Structure {
                      public String m_sername;
                      public String m_username;
                      public String m_password;
                      public short m_tranType;
                      public int m_hChMsgWnd;
                      public int m_nChmsgid;
                      public int m_sockType;
                      public int m_errormsg;
                      public ICallback fun;
         }

    对函数指针的处理

    对函数指针的处理

     public interface ICallback extends StdCallCallback{
         public abstract void fun(NativeLong hHandle,String wParam,int lParam);
     }
    

    OK我们成功的描述的结构体,下面再来修改我的java接口。

     public interface CLibrary extends StdCallLibrary {
         NativeLong VSNET_ServerStart(String m_url,SERVER_UPDATEINFO s,short sho)
     }
    

    到此就全部完成了DLL到JAVA的导出。下面来看如何使用。

     CLibrary INSTANCE = (CLibrary)Native.loadLibrary("demoC", CLibrary.class);
     ICallback C = new CallbackImp();
     CLibrary.SERVER_UPDATEINFO su = new CLibrary.SERVER_UPDATEINFO();
     su.m_sername = "sername";
     su.m_username = "username";
     ...
     su.fun = C;
     short sho = 3000;
     NativeLong nl = CLibrary.INSTANCE.VSNET_ServerStart("url",su,sho);
    

    OK,搞定。

    注意: 1、函数、结构体定义的名称必须和DLL中的一样。 2、函数结构体的参数顺序必须一样

  • 相关阅读:
    ECNU-2574 Principles of Compiler
    C++调用C#生成的DLL文件的各种问题
    EOJ-1708//POJ3334
    Linux---弹球游戏
    dotfiles管理
    js基础的知识整理
    关于css的一些知识点整理
    HTML5 aria- and role
    JS获取非行间样式
    Javascript中的数组去重-indexof方法
  • 原文地址:https://www.cnblogs.com/zhangxsh/p/3636023.html
Copyright © 2011-2022 走看看