`
libaohan
  • 浏览: 45422 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论
阅读更多
[原创]JNI完整的可行实例(绝对适合初学者)
踩踩 0作者:nicegiving 发表日期:2009-09-12 复制链接 收藏
最近需要用到些JNI的东西,在网上找了找资料,感觉说的不是很详细,初学者容易误入歧途,于是决定自己写一个教程,一是为了使自己更加熟悉JNI的基本操作流程,二是为了给广大初学者服务。

本文的七个大标题就是我总结出来的JNI的基本流程,在JNI中,本地化的方法是通过库文件为Java程序使用的,因此我们不但要编写Java程序,而且还需要有包含有本地化方法的库文件,这需要我们自己编写C++代码来编译生成。然后将生成的库文件拷贝到java的class文件或者jar路径中,然后运行class文件或者jar文件,这些库文件就会被自动的加载然后为Java程序服务。

在本文中,我们以一个例子贯穿其中,演示基本的JNI操作。
一、编写Java类
/**
??* File name: Testdll.java
??* JNI 演示基本程序
??* @author Zengming Zhang
??*/
public class Testdll {
??
??/*
?? * 首先要加载本地系统的库文件,windows下面是dll文件,Linux/Unix下面是so文件,
?? * 不需要给出扩展名,系统会为我们决定使用什么扩展名的文件。
?? */
??static{
????System.out.println("Loading library ...");
????System.loadLibrary("zzmdll"); // 加载本地的zzmdll.dll库文件
????System.out.println("Loading library completed");
??}
??
??/*
?? *?? 定义一个本地化的get函数和一个本地化的set函数,
?? *?? 在这里只需要声明就好,不需要实现,因为实现是在C++中完成的。
?? *?? 注意函数声明中的native关键字,这说明定义的方法是和本地系统密切相关的。
?? */
??public native static int get();
??public native static void set(int i);
??
??/*
?? * 测试函数
?? */
??public static void main(String args[]){
????Testdll test = new Testdll();
????test.set(199);
????System.out.println(test.get());
??}
}

二、编译Java类
我们使用javac命令来编译java文件,如下所示:
>javac Testdll.java
然后会生成Testdll.class文件,这个时候你如果运行这个文件的话肯定会报错的,因为java程序找不到要加载的类。

三、使用javah生成类库的头文件
对于为什么要这样做是很容易理解的,我们在java类中定义了自己的本地化方法的声明,但是这只是在java文件里面声明,但是实现却是要在C++程序里面,而在C++程序里面我们并不知道需要实现的函数原型,所以,我们需要一个头文件来为我们定义C++程序可以理解的函数原型,一般来说,这种东西都是存放在.h文件里面,而我们使用javah命令就是生成这种.h文件。
具体的命令执行如下所示:
>javah Testdll
然后我们就会在Testdll.class同目录下面发现生成的.h文件,文件名是Testdll.h,下面是该文件的内容:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Testdll */
#ifndef _Included_Testdll
#define _Included_Testdll
#ifdef __cplusplus
extern "C" {
#endif
/*
??* Class:???????? Testdll
??* Method:?????? get
??* Signature: ()I
??*/
JNIEXPORT jint JNICALL Java_Testdll_get
?? (JNIEnv *, jclass);
/*
??* Class:???????? Testdll
??* Method:?????? set
??* Signature: (I)V
??*/
JNIEXPORT void JNICALL Java_Testdll_set
?? (JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif

你会发现这个文件里面有很多新的名词,比如JNIEXPORT、jint等,JNIEXPORT是说这些函数是要被java调用的,jint是为了使java中的int和本地系统的int相互理解的中间体,我们就可以理解成int,你肯定也会猜到还有很多这样的定义,没错,这些都是JNI特有的,这些东西的定义在jni.h文件中(文件在JDK目录下面的include文件夹中)。

函数的声明方式,特别是函数的名字也是很有意思的,我们在java程序中的函数名字是get和set,而在这个头文件当中,函数的名字由三部分组成,Java打头的部分,说明是java调用的函数,然后是java类的class path路径,最后是java程序中定义的函数名,三部分使用下划线连接。

其他的没有什么好说的了。

四、编写对应的头文件的实现
这个部分就是本地化的C++开发了,我们要编写对应的函数的本地化实现,然后编译生成dll文件,这部分我使用VS2008来实现。

第一步,建立dll项目: 文件->新建->项目,在左边的Visual C++下面选择Win32,然后在右边的模板那里选择Win32项目,之后输入项目的名称,选择路径,点击确定按钮。在之后的Win32应用程序向导中,点击下一步,选择dll,其他的都不要勾选(当然默认是勾选预编译头的),点击完成按钮。

第二步,建立头文件:我们需要将用javah生成的Testdll.h文件弄过来,你可以新建一个,或者添加现有项。

第三步,编写实现文件(源文件):新建一个源文件,文件名是Testdll.cpp,该文件的具体内容如下:
#include "stdafx.h"
int i = 0;
JNIEXPORT jint JNICALL Java_Testdll_get
?? (JNIEnv *, jclass){
??return i;
}
JNIEXPORT void JNICALL Java_Testdll_set
?? (JNIEnv *, jclass, jint j){
??i = j;
}

第四步,修改stdafx.h文件:添加我们需要引用的头文件,即jni.h和Testdll.h两个文件,添加后的该文件内容如下:
// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN???????????????????????? // 从 Windows 头中排除极少使用的资料
// Windows 头文件:
#include <windows.h>
// TODO: 在此处引用程序需要的其他头文件
#include <jni.h>
#include "Testdll.h"

五、编译生成*.dll文件(需要配置jni.h的路径,不然编译会出错)
由于VS2008默认是没有包含jni.h文件的,所以我们需要先设置下,不然编译会出错,设置方法如下,将以下文件:
\jdk\include\jni.h
\jdk\include\win32\jawt_md.h
\jdk\include\win32\jni_md.h
复制到VS2008安装目录下的\VC\include目录中即可。

然后右击工程,选择生成,如果没有错误的话,我们会在工程目录下面的debug路径下面找到编译生成的dll文件。

六、拷贝生成的*.dll文件到Java类的class文件路径下
将在第五步中生成的dll文件拷贝到java的.class或者jar路径下面即可,确保他们在同一目录中。

七、运行class文件
现在我们运行Testdll.class文件就不会出现错误了,具体的运行情况如下:
D:\Projects\Java-projects\workspace-4\JNI-example\bin>java Testdll
Loading library ...
Loading library completed
199

如果您有任何问题请联系我:nicegiving@gmail.com,欢迎学习交流!
分享到:
评论

相关推荐

    Unity3D教程:GUILayout.Window和GUI.Window的区别1

    在Unity3D开发中,GUI系统提供了一种创建用户界面(UI)的方式,而GUILayout和GUI.Window是其中的两个重要工具,它们用于构建游戏中的窗口和控件。本教程将详细探讨GUILayout.Window与GUI.Window之间的差异,帮助...

    windowbuilder1.9.3.zip

    WindowBuilder是Eclipse IDE中的一个强大工具,专用于简化Swing和 SWT(Java窗口小部件工具包)应用程序的开发。1.9.3版本的WindowBuilder提供了对这些框架的直观图形化界面,允许开发者通过拖放组件来创建用户界面...

    windowbuilder安装教程.zip

    WindowBuilder是Eclipse集成开发环境(IDE)中的一个强大工具,专门用于简化Java GUI(图形用户界面)的设计工作。在Eclipse Mars 4.5版本中,安装WindowBuilder可能需要一些特殊的步骤,因为并不是所有公开的教程都...

    X-Window程式设计入门 教程

    X Window 程式设计入门--第一章 什么是 X Window X Window 程式设计入门--第二章 X Programming 的第一步 X Window 程式设计入门--第三章 绘图(Graphic) X Window 程式设计入门--第三章 绘图(Graphic) X Window 程...

    window.showModalDialog模式对话框和 window.open的区别

    `window.showModalDialog` 和 `window.open` 都是JavaScript提供的两种打开新窗口的方法,但它们在功能和使用场景上有着显著的区别。 首先,我们来详细探讨`window.showModalDialog`。`showModalDialog`方法用于...

    window.open.txt

    根据提供的文件信息,我们可以深入探讨`window.open()`方法在不同浏览器环境下的特性和使用细节。 ### window.open() 方法概述 `window.open()`是JavaScript中一个非常实用的方法,它用于在一个新的浏览器窗口或...

    IFrame AND window对象

    在Web开发中,`IFrame`(Inline Frame)和`window`对象是两个非常重要的概念,它们在构建复杂的网页布局和交互中起着关键作用。`IFrame`允许我们在一个HTML文档中嵌入另一个HTML文档,而`window`对象则是浏览器提供...

    window.open最大化问题

    Window.open 最大化问题解决方案 Window.open 是 JavaScript 中的一个方法,用于打开新的浏览器窗口。然而,在实际应用中,我们经常需要将弹出的窗口最大化,以便更好地展示内容。在本文中,我们将探讨如何使用 ...

    Window.Open详解

    ### Window.open() 方法详解 #### 一、方法简介 `window.open()` 是一个在Web开发中经常被用来创建新浏览器窗口或标签页的方法。此方法是 `window` 对象的一个属性,通过调用该方法可以指定打开的新窗口的URL、...

    X Window 系统使用指南

    X Window System 是一套在各种位元映像显示器 (bitmapped dispalys) 上具有极大可携性 (portable) 的视窗系统 (window system), 它是由麻省理工学院 (MIT)所发展出来. X Windows System ( 本书以後部 份简称为...

    WindowBuilder Pro安装

    WindowBuilder Pro是一款强大的Java GUI(图形用户界面)开发工具,尤其适用于SWT和JFace技术。它被设计成一个Eclipse插件,极大地简化了GUI应用程序的创建过程,通过直观的拖放界面和代码自动生成功能,使得开发者...

    WindowBuilder下载,eclipse离线安装(附带步骤)

    Eclipse可视化开发之windowBuilder插件,eclipse插件,为2019-07-16当前最新版的WindowBuilder插件&gt;&gt;repository.zip,该插件为离线安装, 以下为安装步骤: 离线安装说明 1,把下载的windowbuilder.zip,解压出...

    重写window.alert方法

    在JavaScript编程中,`window.alert()` 是一个内置的全局函数,用于向用户显示警告对话框,通常包含一条消息和一个“确定”按钮。这个方法在网页开发中常用于简单的信息提示,但有时开发者可能需要自定义其行为,...

    字符串 window.open() window.opener window.name window对象等的总结

    在JavaScript的世界里,`window`对象是全局对象,它提供了与浏览器窗口进行交互的各种方法和属性。本篇文章将深入探讨`window.open()`、`window.opener`、`window.name`以及`window`对象的一些核心概念,同时通过两...

    window.open最大化操作

    Window.open最大化操作 在Web开发中,我们经常需要弹出新的浏览器窗口,而在某些情况下,我们需要将这个窗口最大化以便于用户体验。那么,如何使用JavaScript的window.open方法来实现窗口的最大化呢? 首先,让...

    window.open打开新窗口参数设置

    ### window.open 打开新窗口参数设置详解 在前端开发中,`window.open()` 方法是浏览器内置的一个功能,用于在JavaScript中打开新的浏览器窗口。本文将深入探讨如何使用 `window.open()` 方法及其参数设置,帮助...

    javascript 打开页面window.location和window.open的区别.docx

    ### JavaScript打开页面window.location与window.open的区别 #### 一、概述 在JavaScript中,`window.location` 和 `window.open` 都是用来控制浏览器导航的重要API,但它们在使用场景、功能特性和行为上有显著的...

    window.open父子窗口传值问题

    在Web开发中,`window.open` 是一个JavaScript函数,它用于打开新的浏览器窗口或标签页。这个函数在处理用户交互,比如点击按钮打开新页面,或者在不同窗口间传递数据时非常常见。当我们谈论“window.open父子窗口...

    window.showModalDialog以及window.open用法简介

    Window.showModalDialog 和 Window.open 用法简介 Window.showModalDialog 和 Window.open 都是 JavaScript 中的方法,用于创建新窗口或对话框,下面分别介绍它们的用法和参数。 一、Window.open() 方法 Window....

Global site tag (gtag.js) - Google Analytics