java通过 jni 调用C++动态库----上篇
原文链接:https://blog.csdn.net/Oyasimi1412/article/details/82259597
1:首先新建一个java的项目(项目)名为的HelloWorld
暂时不创建moudle,这里简单例子不需要这个。
2:在SRC目录上创建一个包(包)名为com.jni
3:再在包com.jnishang创建两个类HelloWorld和Test Dll
大家同理创建TestDll类。
helloWorld.java源代码如下:
package com.jni; public class HelloWorld { static { System.loadLibrary("mydll"); } public native void displayHelloWorld(); }
上面的mydll就是我们下一篇将要用到的动态库,这里先这样写。
TestDll.java源代码如下:
package com.jni; public class TestDll { public static void main(String[] args) { // TODO Auto-generated method stub HelloWorld helloWorld = new HelloWorld(); helloWorld.displayHelloWorld(); } }
相关代码注意在ecilpse里面做一下保存工作,不然后面的命令行有可能失败
到这里准备工作基本结束:
先编译HelloWorld.java,我们这里使用命令行编译
先在电脑到达这个目录d:\ Eclipse的工作空间\的HelloWorld \ SRC \ COM \ JNI
也就是两个的的java文件所在目录,如下:
shift +鼠标右键进入命令行,如下:
。我们先编译出类文件使用命令javac的的:
命令如下:javac HelloWorld.java
成功后在同一目录就可发现HelloWorld.class的文件了,如下:
接下来要编译我们最重要的.H文件了,这里我搞了很久,本来是用JAVAH命令来编译,网上也有大量的相关教程,但是我用的jdk10,新版本的JDK已经去除了javah.exe ,也就是说不能再用javah命令了,jdk9开始就提供了javac -h命令代替,经过一些尝试,我还是弄出来了javac -h命令的用法。
希望了解JAVAH用法的朋友请参考别的同学的分享,由于我本机已经无法执行JAVAH命令,所以没有这方面的说明给大家,这块的文档网上应该很多
我们需要先让命令行回到D:\ eclipse-workspace \ HelloWorld \ src目录,通过两个命令行cd ..就可以回来,如下:
现在我们已经回到了D:\ eclipse-workspace \ HelloWorld \ src目录,接下来执行javac -h命令,这里的目录一定不要弄错了,希望读者,按要求操作。
执行javac -h.COM \ JNI \ HelloWorld.java
然后就可以在SRC目录下找到com_jni_HelloWorld.h
到了这里,我们与C ++交互的.h文件就有了,com_jni_HelloWorld.h源码如下
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_jni_HelloWorld */ #ifndef _Included_com_jni_HelloWorld #define _Included_com_jni_HelloWorld #ifdef __cplusplus extern "C" { #endif /* * Class: com_jni_HelloWorld * Method: displayHelloWorld * Signature: ()V */ JNIEXPORT void JNICALL Java_com_jni_HelloWorld_displayHelloWorld (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
注意,不要修改这个头文件。
到这里,关键的头文件就生成了,接下来一篇介绍如何使用生成的这个头文件
java通过 jni 调用C++动态库----下篇
上篇介绍了 通过命令行生成了一个.h 文件 com_jni_HelloWorld.h
本章介绍如何使用这个文件
先创建DLL,过程如下:
工具vs2017
创建动态库DLL给第三方使用
步骤:
1,文件 - >新建 - >项目,出现弹框如下:
选择Windows桌面 - > windows桌面向导
接着是这个界面:
选择动态链接库,空项目,再点击确定即可
接下来新建头文件和源文件
在这里添加一个头文件和源文件
头文件上右键,添加,新建项
源文件同理添加
完成之后,如图:
之后在.h和cpp中添加相关代码即可,头文件中添加导出函数接口,cpp具体实现
.H文件中类似代码如下:
#ifndef _MYDLL_H_ #define _MYDLL_H_ #ifdef MYDLL_EXPORTS #define MYDLL_API __declspec(dllexport) #else #define MYDLL_API __declspec(dllimport) #endif #ifdef __cplusplus extern "C" { #endif MYDLL_API int Add(int a, int b); #ifdef __cplusplus } #endif #endif //_MYDLL_H_
CPP中类似代码如下:
#include "mydll.h" int Addin(int a, int b) { return a+b; }
项目属性方面也需要修改:
项目属性,C / C ++,预处理器添加
_AFXDLL
_AFXEXT
MYDLL_EXPORTS
预处理这里,可能各有不同,大家可根据自己的编译情况,自由添加。
另外个人还有一些习惯,习惯如下配置项目属性:
之后坐一些编译,可以看见编译出来了DLL文件
但是看不到lib文件
如果需要导出LIB文件,我们需要做一些操作:
在项目上右键,添加,新建项;
选择代码项,模块定义文件,DEF文件项
之后在编译,就可以看见的lib文件了
DEF文件内可如下写代码:
-
LIBRARY "mydll"
-
EXPORTS
-
Add @1
到这里添加动态库就结束了
假设我们现在生成一个动态库mydll
有头文件和源文件,mydll.h,mydll.cpp,该项目中mydll.h中没有内容,我们可以将它去除
把 上一篇生成的com_jni_HelloWorld.h 放到我们的工程目录下,并导入工程mydll中
如下所示:
接着是下一步操作
在mydll.cpp中实现那个接口,打印helloworld
#include "com_jni_HelloWorld.h" JNIEXPORT void JNICALL Java_com_jni_HelloWorld_displayHelloWorld(JNIEnv *, jobject) { printf("Hello World!\n"); }
之后编译,会报错,需要引入两个头文件,jni_md.h 和 jni.h,这两个是jni依赖的文件,依次在我们安装jdk时候的两个目录文件夹下,我这边的是这个目录
C:\Java\jdk-10.0.2\include\win32
C:\Java\jdk-10.0.2\include
将这两个目录附件包含目录到工程里面去,如下操作
注意上方有win32 和x64之分,如果你的eclipse是64位的,将不能使用32位的dll。
编译工程,得到一个64位,mydll.dll文件。
之后把这个dll文件拷贝到 JRE安装路径下的bin文件夹内,运行java程序即可。结果如下:
这样完成了java通过jni调用C++动态库的过程,朋友们可通过上下两篇实现该功能