JNI中利用java调用底层C++代码

JNI学习之java调用底层C/C++代码输出简单HelloWorld

1、JNI介绍及平台工具简介

JNI是Java本机接口(Java Native Interface),是一个本机编程接口,它是Java软件开发工具箱(Java Software Development Kit,SDK)的一部分。JNI允许Java代码使用以其他语言编写的代码和代码库。Invocation API(JNI的一部分)可以用来将Java虚拟机(JVM)嵌入到本机应用程序中,从而允许程序员从本机代码内部调用Java代码。

不过,对Java外部的调用通常不能移植到其他平台,在applet中还可能引发安全异常。实现本地代码将使您的Java应用程序无法通过100%纯Java测试。但是,如果必须执行本地调用,则要考虑几个准则:

1.将您的所有本地方法都封装到一个类中,这个类调用单个的DLL。对每一种目标操作系统平台,都可以用特定于适当平台的版本的DLL。这样可以将本地代码的影响减少到最小,并有助于将以后所需要的移植问题考虑在内。

2.本地方法尽量简单。尽量使您的本地方法对第三方(包括Microsoft)运行时DLL的依赖减少到最小。使您的本地方法尽量独立,以将加载您的DLL和应用程序所需的开销减少到最小。如果需要运行时DLL,必须随应用程序一起提供。

平台和工具:

目的:java调用C++输出HelloWorld

工具:MyEclipse、Visio Studio 2015

平台:Windows 7 64位旗舰版

2、Java代码编写处理

在MyEclipse中新建项目并编写用来调用底层函数的代码如下:

package cn.iot.wikey;

public class JNIDemo {
    public native void sayHello();

    /**
     * @Wikey
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.loadLibrary("JNIDll");
        JNIDemo jniDemo = new JNIDemo();
        jniDemo.sayHello();
    }

}

上面代码中首先在类JNIDemo中用native关键字修饰一个方法,native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。

而此时我们用native修饰的这个sayHello就是底层要实现的方法,在main中我们首先通过System.loadLibrary()方法去调用底层代码生成的动态链接库dll文件,下面会讲到。

3、利用jdk自带的javah生成底层代码可引入的.h文件

首先在dos中进入java项目文件目录,在src中利用命令javah 包名.类名生成一个.h文件,此时文件会出现在src目录中如下:

这样就可以了。

4、用VS 2015生成.dll文件

在这,首先说一个问题,在编写底层代码的时候,用什么样的c/c++ IDE工具是很重要的,因为要考虑自己在什么样的平台下面生成这个动态链接库,你要保证这个工具可以生成一个64位的.dll文件,因为大多数工具都可以生成win32的动态链接库,经过几个工具的尝试,我最终还是选择下载安装了这个庞然大物,话说这个VS真是个全家桶,各种东西都有,大的要死啊有木有,废话不说了,继续,打开VS2015,点击新建,创建一个新的项目:

点击Win32控制台应用程序,在下面输入您的项目名称和位置,点击确定即可:

在此处注意选择DLL,并且要点击空项目,然后点击完成就会自动创建一个新的项目,在你的主文件中,加入下面的这行代码,

#include<iostream>
using namespace std;
#include "cn_iot_wikey_JNIDemo.h"  

JNIEXPORT void JNICALL Java_cn_iot_wikey_JNIDemo_sayHello(JNIEnv * env, jobject obj)
{
    cout << "Hello World" << endl;
}

注意:这里面的iostream不应该带有.h后缀,因为VS似乎跟VC是不同的,而且using namespace std需要加上,所谓namespace,是指标识符的各种可见范围,而C++标准程序库中的所有标识符都被定义于一个名为std的namespace中,如果不用也可以,除非你不想用cout和endl等标准程序库中的标识符。

然后这个时候我们编译C++函数,发现此时是有文件缺失错误出现的,原因是我们没有把文件拷贝过来,那些文件呢,聪明的你肯定猜到了,我们之前生成的cn_iot_wikey_JNIDemo.h文件,另外还有他需要的jni.h,还有jni.h所依赖的jni_md.h,后面这两个文件在JDK的include中可以找到,请大家自行寻找,然后加上就可以。

上图中下面这个函数你可以自己写,但是要保证Java_cn_iot_wikey_JNIDemo_sayHello的名称与我们之前生成的cn_iot_wikey_JNIDemo.h头文件中函数名称相同,cn_iot_wikey_JNIDemo.h文件如图:

以后可以根据这个函数,在C/C++中实现各个我们在JAVA中需要的函数,只要保证名称一样就可以咯。

这些做完之后,我们就可以进行编译了,我在编译运行的时候,VS报了一个错误:缺少kernel32.dll文件,这个时候只需要修改下面这个地方应该就可以了,但是不一定,因为每个人的平台还有安装版本不一样,这里我不多描述。以免误导:

这个地方的包含目录要有 (WindowsSDKIncludePath) (WindowsSDK_LibraryPath_x86)或者$(WindowsSDK_LibraryPath_x64)才可以。

这样的话就可以生成.dll文件了,至于什么样的.dll文件,您可以选择这里相应的生成即可:

这样的话就可以成功生成64位.dll文件了。在项目目录的X64文件中可以找到。

5、添加dll,运行程序

此时生成了一个64位.DLL文件了,但是需要改一下名词,跟我们System.loadLibrary中的名字是一样的才可以,然后将.dll文件放到C:/WINDOWS/SYSTEM32中即可,运行MyEclipse中我们的java程序如图即可看到显示结果了:

这样的话,我们就成功的了解并实际操作了java中跟底层代码调用的JNI步骤了,剩下的就是赶紧去撸我们要实现的具体功能了,拜拜!!!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值