网站建设| 数据库类| 图形图象| 程序设计| 现代办公| 操作系统| 考试认证| 网络技术| 软件工程| 电脑相关| 文学作品
网站开发| 网页制作| 操作系统| 图象图形| 考试认证| 数据库类| 程序设计| 硬件技术| 现代办公| 网络技术| 笑话频道
 
您的位置: 电脑书库首页-> 电脑文摘-> 程序设计-> C/C++/VC-> 例解用 VC++ 6.0 实现 JNI

例解用 VC++ 6.0 实现 JNI
作者:佚名 来源:InterNet 加入时间:2005-1-28
相关文章
  • VC实现PC并行端口数字信息输入/输出
  • VC下编程实现3D文字
  • 相关书籍:
  • VC使用大全
  • vchome_graph
  • VC++.NET开发驱动程序详解
  • VC++ 编程指南
  • VC知识库电子杂志41-45期
  • Visual C++ 入门到精通-VC++与Internet
  • VC技术内幕第五版
  • JNI是JDK的一部分,用于为Java提供一个本地代码的接口。通过使用JNI编写的程序能够确保你的代码能够完全的移植到所有的平台。JNI使得运行在JVM虚拟机上的Java代码能够操作使用其它语言编写的应用程序和库,比如C/C++以及汇编语言等。此外JNI提供的某些API还允许你把JVM嵌入到本地应用程序中。下图表达了JNI所扮演的角色。



    本文将通过一个实例来阐述使用VC++6.0来实现JNI的完整过程。使用JNI来整合本地代码和Java代码的步骤是确定的,没有再创作的余地,所以读者可以通过本文的步骤来逐步认识到,其实Java也是"没有什么不可以"的。

    一、JNI的实现任务描述:在Java中调用windows下的消息框函数,并且从Java中传递一个字符串作为MessageBox函数的显示文本参数,显示在消息框的中间。下面让我们一起进入这一奇妙的旅程。

    Step 1:写一个Java类,在这个类中包含了需要调用的本地方法的描述。

    //WinMsgBox.java
    package edu.netcom.jni;
    public class WinMsgBox  
    {
    	static{
    		System.loadLibrary("WinMsgDll");    // (1)
    	}
    	public native void showMsgBox(String str);  // (2)
    }



    (1)中WinMsgDll是动态链接文件的文件名,不用加扩展名,因为在不同的平台下动态链接文件扩展名是不同的,由JVM自动识别,比如在Solaris下,会被转换为WinMsgDll.so;而Win32环境下会转换为WinMsgDll.dll。这个文件名必须和Step 4中生成的文件名一致。这个文件的存放位置也很重要,它只能被放在JVM属性值java.library.path中指定的文件夹中。这个属性值可以使用System.getProperty("java.library.path");来查看。一般情况下,至少放在这几个位置是确定可靠的,windows安装目录下的system32下面,JDK安装目录下的bin下面,以及调用主类文件的当前目录。

    (2)中指明了你必须用本地代码实现的方法。

    Step 2:提示符下使用命令javac -d . WinMsgBox.java编译Step 1编写的java文件。

    此时会在当前目录下建立一个edu\netcom\jni目录结构,并且一个WinMsgBox.class文件存在其中。

    Step 3:提示符下使用命令javah -jni edu.netcom.jni.WinMsgBox,此时会在当前目录下产生一个edu_netcom_jni_WinMsgBox.h文件,注意这个文件名是由(包名+类名)组成,中间用(_)隔开。此文件内容如下:

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>                       // (1)
    /* Header for class edu_netcom_jni_WinMsgBox */
    
    #ifndef _Included_edu_netcom_jni_WinMsgBox
    #define _Included_edu_netcom_jni_WinMsgBox
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     edu_netcom_jni_WinMsgBox
     * Method:    showMsgBox
     * Signature: (Ljava/lang/String;)V       // (2)
     */
    JNIEXPORT void JNICALL Java_edu_netcom_jni_WinMsgBox_showMsgBox
      (JNIEnv *, jobject, jstring);           // (3)
    
    #ifdef __cplusplus
    }
    #endif
    #endif


    (1)包含的jni.h存在于JDK安装目录下的include下面。

    (2)(Ljava/lang/String;)V这是函数的标记符,当从本地方法端访问Java端的方法时,会用到这个标记符。JNI中为每种数据类型也定义了标记符,标记符的规则请查看JNI标准文档。

    (3)在WinMsgBox.java中本地方法void showMsgBox(String str);的定义,被映射为JNIEXPORT void JNICALL Java_edu_netcom_jni_WinMsgBox_showMsgBox(JNIEnv *, jobject, jstring); 其中函数名的映射规则是(Java_包名_类名_方法名),如果存在重载的方法,则在后面还会增加每个参数的标记符。每一个方法映射到本地C函数后都会增加两个参数:JNIEnv *和jobject,关于这两个参数的用法将在后面阐述。另外,所有Java中的数据类型都会按一定规则进行映射为本地数据类型,这些数据类型都是在jni.h中定义的。下面分别按照基本数据类型,和对象类型列出。

    表1 Java基本类型到本地类型的映射



    表2 Java中的类到本地类型的映射



    Step 4:使用VC来编写本地方法的实现函数,最后编译成.dll文件。过程如下:

    1) 选择new->projects(选择Win32 Dynamic-Link Library,以Step 1中指定的库名WinMsgDll作为工程名)->OK->An ampty DLL project->Finish。

    2) 选择Tools->Options->Directories(添加目录D:\J2SDK1.4.2_03\INCLUDE和D:\J2SDK1.4.2_03\INCLUDE\WIN32)。在这些目录中包含JNI所需的头文件。

    3) 将Step 3生成的edu_netcom_jni_WinMsgBox.h拷贝到WinMsgDll工程文件夹中。然后FileView中添加这个头文件。

    4) 添加源文件WinMsgDll.cpp,内容如下:

    #include "windows.h"
    #include "edu_netcom_jni_WinMsgBox.h"
    /*
     * Class:     edu_netcom_jni_WinMsgBox
     * Method:    showMsgBox
     * Signature: (Ljava/lang/String;)V
     */
    JNIEXPORT void JNICALL Java_edu_netcom_jni_WinMsgBox_showMsgBox
    (JNIEnv * env, jobject obj, jstring str){
    	const char *msg;
    	msg = env->GetStringUTFChars(str,0);
    	MessageBox(NULL,msg,"Java invoke",MB_OK);
    	env->ReleaseStringUTFChars(str,msg);
    }


    5) 编译生成WinMsgBox.dll文件。并将这个.dll文件拷贝到Step 1中说明的目录中。

    注意:

    1) 我们知道dll文件有两种指明导出函数的方法,一种是在.def文件中定义,另一种是在定义函数时使用关键字__declspec(dllexport)。而在JNI中函数定义中的关键字JNIEXPORT实际在jni_md.h中如下定义,#define JNIEXPORT __declspec(dllexport),可见JNI默认的导出函数使用第二种。使用第二种方式产生的导出函数名会根据编译器发生变化,在有的情况下会发生找不到导出函数的问题(我们在JSP中使用JNI时就发生了这种问题,百思不得其解,后来强行加入一个.def文件就解决了)。因此最好是使用第一种方法自己定义一个.def文件来指明导出函数,这种情况下会强制使用第一种方式产生导出函数。本例中可以加入一个WinMsgDll.def文件,内容如下:

    LIBRARY      "WinMsgDll"
    DESCRIPTION  'message Windows Dynamic Link Library'
    EXPORTS
        ; Explicit exports can go here
    	Java_edu_netcom_jni_WinMsgBox_showMsgBox


    2) 从本例中,我们可以看到WinMsgBox.java决定了edu_netcom_jni_WinMsgBox.h,而后者又决定了WinMsgDll.dll,也就是说,这是一个"牵一发而动全身"的过程,如果你改动了WinMsgBox.java,就一定要把整个步骤都走一遍(这一点一定要切记,因为这也是我们跌得鼻青脸肿后才得出的警世良言)。

    3) 生成的.dll文件一定要正确拷贝到Step 1说明的目录中,本例中是将生成的WinMsgDll.dll和Step 5中的测试文件放在同一个目录下的(这也是我们困惑了很久才解决的问题)。

    Step 5:编写一个测试文件来测试对WinMsgDll.dll的调用。测试文件TestJNI.java内容如下:

    //TestJNI.java
    import edu.netcom.jni.WinMsgBox;
    public class TestJNI 
    {
    	public static void main(String[] args) 
    	{
    		     WinMsgBox box = new WinMsgBox();
    		box.showMsgBox("Wonderful!!");
    	}
    }


    编译,运行,windows下的对话框跃然屏幕中间。到此为此,整个JNI的实现过程就已经完成了。

    [文章录入员:nancy]

    相关文章
  • VC实现PC并行端口数字信息输入/输出
  • VC下编程实现3D文字
  • 相关书籍:
  • VC使用大全
  • vchome_graph
  • VC++.NET开发驱动程序详解
  • VC++ 编程指南
  • VC知识库电子杂志41-45期
  • Visual C++ 入门到精通-VC++与Internet
  • VC技术内幕第五版
  • 本站推荐内容

    近期主机类热搜关键词:
    美国服务器 美国服务器租用 海外服务器租用 国外服务器租用

    C/C++/VC
    C/C++/VC
    C++Builder
    Basic/VB类
    Delphi/Pascal
    Java编程
    FORTRAN
    其它
    电脑教程阅读排行
    ·新手入门:c++经典
    ·VC开发实例
    ·ping的源程序
    ·Visual C++编程技巧之一
    ·Visual C++程序设计中的...
    ·Windows 中不规则窗体的编...
    ·扔掉Socket实现网络编程
    ·例解用 VC++ 6.0 实现 ...
    ·VC实现PC并行端口数字信息输入...
    ·轻轻松松C to C++(一)