【转载】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、函数结构体的参数顺序必须一样
【转载】java调用C++写的DLL的更多相关文章
- c++ c# java 调用 c++ 写的dll
1. vs 中新建win32 dll 项目 testdll 添加实现文件 test.cpp #include "stdafx.h" #include <ios ...
- 通过COM组件方式实现java调用C#写的DLL文件
转自这里 最近一段时间单位在做一个Web项目,工程师用JAVA语言,需要公用人员信息,统一用户名和密码,原有的平台中是用C#语言开发的,在网上查找解决方法,通过JAVA调用C#的DLL文件实现.网上资 ...
- 通过COM组件方式实现java调用C#写的DLL文件 转
最近一段时间单位在做一个Web项目,工程师用JAVA语言,需要公用人员信息,统一用户名和密码,原有的平台中是用C#语言开发的,在网上查找解决方法,通过JAVA调用C#的DLL文件实现.网上资料很多,自 ...
- 实现通过COM组件方式实现java调用C#写的DLL文件的完整demo
最近因为工作需要,客户那边工程师使用的是JAVA语言开发的程序,我们这边平台中是用C#语言开发的,因为有些操作必须统一,所以我在网上查找解决方法,自己也实践过,在这里做个笔记吧,分享一下. 声明:下面 ...
- c++调用c#写的DLL
c++调用c#写的DLL: 此文章演示了建立c#的dll: c++建立工程,引入dll: 不能解决的问题: 指定dll的路径,在代码里面直接写 #using "xxx.dll" 必 ...
- QT调用C#写的Dll
参见: https://blog.csdn.net/weixin_42420155/article/details/81060945 C#写的dll是没有dllMain入口函数的,是一种中间语言,需要 ...
- Delphi7程序调用C#写的DLL解决办法(转)
近来,因工作需要,必须解决Delphi7写的主程序调用C#写的dll的问题.在网上一番搜索,又经过种种试验,最终证明有以下两种方法可行: 编写C#dll的方法都一样,首先在vs2005中创建一个 ...
- 发现个delphi调用vc写的Dll中包括pchar參数报错奇怪现象
发现个delphi调用vc写的Dll中包括pchar參数奇怪现象 procedure中的第一行语句不能直接调用DLL的函数,否则会执行报错,在之前随意加上条语句就不报错了奇怪! vc的DLL源代码地址 ...
- Delphi7程序调用C#写的DLL解决办法
近来,因工作需要,必须解决Delphi7写的主程序调用C#写的dll的问题.在网上一番搜索,又经过种种试验,最终证明有以下两种方法可行: 编写C#dll的方法都一样,首先在vs2005中创建一 ...
随机推荐
- 【剑指Offer】26、二叉搜索树与双向链表
题目描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 解题思路: 首先要理解此题目的含义,在双向链表中,每个结 ...
- 爬虫系列(六) 用urllib和re爬取百度贴吧
这篇文章我们将使用 urllib 和 re 模块爬取百度贴吧,并使用三种文件格式存储数据,下面先贴上最终的效果图 1.网页分析 (1)准备工作 首先我们使用 Chrome 浏览器打开 百度贴吧,在输入 ...
- Q&A to prepare interview of HSBC
1.How do you keep updating lastest IT knowledge? 1).keep an eye on current project technology evetho ...
- 【习题 4-2 Uva201】Squares
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 注意那个星号的数量... 然后V x y的话,是从(y,x)向(y+1,x)连线. H x y才是从(x,y)向(x,y+1)连线 ...
- 洛谷 P3183 BZOJ 4562 [HAOI2016]食物链
题目描述 如图所示为某生态系统的食物网示意图,据图回答第1小题现在给你n个物种和m条能量流动关系,求其中的食物链条数.物种的名称为从1到n编号M条能量流动关系形如a1 b1a2 b2a3 b3.... ...
- ExtJs之ExtJs.Model验证
没有搞好,但知道意思和配置,并且好像4和3的没有兼容性语法,所以网上找了新语法才出来了点东东. <!DOCTYPE html> <html> <head> < ...
- IntelliJ IDEA测试学习网站
IntelliJ IDEA测试学习网站 http://idea.lanyus.com/ 嗯,请支持正版:
- C语言可变參实现參数累加返回
C语言可变參的作用真的是很大,自从发表了可变參怎样实现printf.fprintf,sprintf的文章以来.便有不少博友私信问我实现的机制,我也解释了相关的知识点.今天,我们借着这个机会,再来举一个 ...
- 开发,从需求出发 · 之四 春天在这里
首先,我要大字标语表达立场: 你所使用的framework & non-core features,就跟女人穿在身上的衣服一样,越少越好! watermark/2/text/aHR0cDovL ...
- Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader
Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader 之前写了两篇文章,介绍了我在边缘检測上面的研究.实际上.使用GPU对渲染图像进行边缘检測.前提是须要进行两遍渲染.前 ...