在eclipse下,JAVA通过JNI调用C++方法的简单例子(非android)

最近需要用到这方面的知识,上网搜了一下,发现方法很多,但是试了几种又都没成功,而且很多资料是与android相关的,并不适用于理解JNI和JAVA项目开发,以下给出一种经确认可行的,并且支持较为复杂开发的方法。

用到的工具包括:VS2015,eclipse(我所使用的是4.7版本),当然,,所有的前提是你JAVA已经配置好了,怎么配置这里就不多做赘述了。

首先我们在eclipse下创建一个新项目,项目中创建一个包,包中创建一个类(非常简单的操作),创建好之后项目结构如图:

在eclipse下,JAVA通过JNI调用C++方法的简单例子(非android)_第1张图片

我们的项目名叫JNI_test,包名为jni_test,类名为HelloWorld。本例想实现的效果是JAVA代码调用C++函数实现hello world的输出,对应的JAVA代码如下:

package jni_test;

public class HelloWorld {
	public native void Hello();
	
	static {
		System.loadLibrary("Win32Project1_dll");
	}
	public static void main(String[] args)
	{
		HelloWorld hello = new HelloWorld();
		hello.Hello();
	}
}

看到这篇文章的应该都知道native关键字的左右和static代码块的作用,别疑惑,写上去就好。

基本所有的JNI简单实例文章在此之前都是相同的,但是之后就会出现一些问题。

写好之后我们尝试运行一下,当然会报错,因为你没有dll可以给程序加载,但是这时候我们到eclipse的工作环境下(workplace)打开此项目文件夹,项目文件夹的结构应该如下图:

在eclipse下,JAVA通过JNI调用C++方法的简单例子(非android)_第2张图片

我们需要进入的文件夹是bin,bin文件夹中包含了.class文件。(很多文章中提到这个.class文件是自己用javac生成的,其实并不需要,那样反而容易在实际工程中带来误解,最后连在哪个文件夹下运行都搞不清楚了)。

进入bin的目录一路点到底应该是可以看见.class文件的,如果看不见就回去eclipse中运行一下就好。

bin的目录结构应该为:bin->包名(我的为jni_test )文件夹->.class文件;我们在bin中打开命令行,执行如下javah指令

javah -jni jni_test.HelloWorld

命令行格式为: javah -jni ,参数为连同包名的class文件名,不需要加.class后缀。

执行之后会在bin文件夹中出现一个.h文件,如图:


jni_test_HelloWorld.h代码如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class jni_test_HelloWorld */

#ifndef _Included_jni_test_HelloWorld
#define _Included_jni_test_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     jni_test_HelloWorld
 * Method:    Hello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_jni_1test_HelloWorld_Hello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

好了,到此为止在JAVA 部分需要做的任务已完全结束。


C++部分我们使用VS进行操作,操作步骤如下:

首先创建一个win32程序,选择为dll的空项目。

在eclipse下,JAVA通过JNI调用C++方法的简单例子(非android)_第3张图片

我所使用的版本是vs2015。其余的vs版本应该大致都一样。

这样我们就得到了一个project,用于dll的生成,接下来这几步是比较容易混淆的,大家可以对比着我的图片中进行操作。

首先找到自己的JDK路径下的include文件夹,我的是C:\Program Files\Java\jdk-9.0.4\include;

在此文件夹下找到jni.h文件,在此文件夹下的win32文件夹中找到jni_md.h文件。

找到之后我们将这两个文件和之前得到的jin_test_HelloWolrd.h头文件一起放入VS对应工作目录中,如果是一个新的项目,就应该是工程目录一直选到尽头,与.vcxproj和.filters同一个文件夹中,如下图(下图中多出了一个source.cpp文件,是因为这是我已经构建好的项目,source.cpp是之后c++方法的实现文件,如果待会你们创建.cpp文件与这些头文件在一个目录下,说明操作正确):

在eclipse下,JAVA通过JNI调用C++方法的简单例子(非android)_第4张图片

放入文件夹之后,我们在VS工程目录中添加已有头文件,选取jni_test_HelloWorld.h文件(右键点击Header files,然后选择add existing item):

在eclipse下,JAVA通过JNI调用C++方法的简单例子(非android)_第5张图片

这样我们在视图中就看到了jni_test_HelloWorld.h文件了:

现在点开.h文件,会发现include报错,因为的写法表示从系统库中调用,而jni.h在此处是作为用户库存在,所以将<>改为""后即可消除报错:

即改为        #include"jni.h"。

现在我们可以在源文件中创建一个.cpp文件了,进行自己的编写了,只要#include"jni_test_HelloWorld"即可,函数的定义可以从.h中复制过去,进行实现即可,我的.cpp文件编写如下:

#include "jni_test_HelloWorld.h"
#include
using namespace std;

JNIEXPORT void JNICALL Java_jni_1test_HelloWorld_Hello
(JNIEnv *, jobject) {
	cout << "hello world" << endl;
}

到此在VS中的工作也基本完成,现在注意一个事项,对于dll有对32位的和对64位的,如果是32位操作系统的用户,直接BUILD工程即可(右键project->Build)。如果是64位操作系统的用户,在ECLIPSE中调用32位的dll会报错,所以我们进入VS的项目配置器(右键project->Properties),得到界面如下:

在eclipse下,JAVA通过JNI调用C++方法的简单例子(非android)_第6张图片

先将右上角的Platform改为x64,然后点击右上角configuration manager,进入界面如下:

在eclipse下,JAVA通过JNI调用C++方法的简单例子(非android)_第7张图片

将Active solution platform改为x64,然后应用->确定。

之后进行编译,会在项目文件夹中看到x64文件夹和(如果是32位的就只有Debug文件夹没有x64文件夹),如下:

在eclipse下,JAVA通过JNI调用C++方法的简单例子(非android)_第8张图片

在Debug文件夹中可以找到32位的.dll文件,在x64文件夹中可以找到64位的.dll文件,如下:

在eclipse下,JAVA通过JNI调用C++方法的简单例子(非android)_第9张图片

如果需要使用多个jni的开发者,可以在电脑的某个位置创建一个用于存放.dll文件的文件夹,因为我们待会要把这个路径放入环境变量中,所以把所有.dll放在一起会省事很多,比如我创建了这样的一个文件夹:

D:\experiment\DLL_lib

将.dll放入其中之后我们在环境变量中加入此路径,我在用户变量的Path和系统变量的Path中都添加了此路径,应该是只需要添加一个就好,具体哪一个起作用我并不知道,我添加了两个。

在eclipse下,JAVA通过JNI调用C++方法的简单例子(非android)_第10张图片

在eclipse下,JAVA通过JNI调用C++方法的简单例子(非android)_第11张图片


之后我们关闭eclipse后重新打开,这样eclipse会重新加载库。

然后进入到JNI_test中运行项目(记得把System.loadLibrary()中的库名该为你生成的.dll文件名,不需要加.dll后缀,截图在上文中给出过),构建项目并运行即可,运行结果如下:

在eclipse下,JAVA通过JNI调用C++方法的简单例子(非android)_第12张图片

希望这篇文章能帮助到有需要的人,写的有点繁琐,有更好的方法或者文章中有错误的地方欢迎指出。


参考文章:点击打开链接

你可能感兴趣的:(在eclipse下,JAVA通过JNI调用C++方法的简单例子(非android))