Java JNI学习

    07年的时候就用过JNI这东西了,那时候是为了给项目的J2EE应用写一个授权功能,通过调用vc写的读取硬件id的dll使得cdkey能够跟机器一一对应起来,从而做到控制一个cdkey只能装到一台机器上上。那会儿用的dll是别人写的,java中调用dll也是用的小日本儿写的一个叫jcom的组件,这次决定自己做一遍整个流程.

  1. 编写java文件
    /**
     * Copyright (C), 2009-2010
     * File Name: jni.WinMessage.java
     * Encoding UTF-8
     * Version: 1.0
     * Date: Dec 29, 2009
     * History:	
     */
    package jni;
    
    /**
     *
     * @author (bestirwiny@gmail.com)
     * @version Revision: 1.00 2:12:24 PM
     */
    public class WinMessage
    {
    	static{
    		System.loadLibrary("WinMsgDll");
    	}
    	public native void showMsgBox(String msg);
    }
    

    loadLibrary用于load一个dll,该dll应该在java.library.path定义的路径下啊。

  2. 用javac编译该文件,不用讲。
  3. javah -jni WinMessage,会生成一个jni_WinMessage.h的头文件,下面要做的工作就是dll的编写了。
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include "jni.h"
    /* Header for class jni_WinMessage */
    
    #ifndef _Included_jni_WinMessage
    #define _Included_jni_WinMessage
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     jni_WinMessage
     * Method:    showMsgBox
     * Signature: (Ljava/lang/String;)V
     */
    JNIEXPORT void JNICALL Java_jni_WinMessage_showMsgBox
      (JNIEnv *, jobject, jstring);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    
  4. 创建一个win32动态连接库的工程,将$JAVAHOME/include,$JAVA_HOME/include/win32目录加入到工程需要引用的头文件路径中。
    #include "tchar.h"
    #include "stdlib.h"
    #include "stdio.h"
    #include "AtlBase.h"
    #include "AtlConv.h"
    #include "windows.h"
    #include "jni_WinMessage.h"
    
    /*
     * Class:    
     * Method:    showMsgBox
     * Signature: (Ljava/lang/String;)V
     */
    JNIEXPORT void JNICALL Java_jni_WinMessage_showMsgBox
      (JNIEnv * env, jobject jobj, jstring str){
    	const char * msg;
    	msg = env->GetStringUTFChars(str,0);
    
    	WCHAR* strA;
        int i= MultiByteToWideChar ( CP_UTF8 , 0 ,msg ,-1 ,NULL,0);
    	strA = new WCHAR[i];
    	MultiByteToWideChar ( CP_UTF8 , 0 ,( char * ) msg, -1, strA , i );
    
    	USES_CONVERSION;
    	MessageBox(NULL,strA,_T("Java invoke "),MB_OK);
    	env->ReleaseStringUTFChars(str,msg);
    }
    

    由于win32变成才开始学,所以这个东西弄了好久才弄好,网上的例子中通过GetStringUTFChars取回的msg直接传到MessageBox中用,可我用的是VS2008,直接用会报错误,大致是说不能将const char *转换为LPCWSTR * ,
    LPCWSTR是long pointer constant wide string的意思,是一种wchar_t类型,char类型占用一个byte,而wchar_t占用两个byte,所以这边就要用一个转换 函数,网上查好久才查到MutiByteToWideChar函数,才解决了中文乱码的问题。

  5. 编译完会成成一个dll文件,拷贝到java.library.path下,我是拷贝到了c:\windows下。
  6. 编写一个java类调用上面的WinMessage
    /**
     * Copyright (C), 2009-2010
     * File Name: jni.TestWinMessage.java
     * Encoding UTF-8
     * Version: 1.0
     * Date: Dec 29, 2009
     * History:	
     */
    package jni;
    
    /**
     *
     * @author (bestirwiny@gmail.com)
     * @version Revision: 1.00 4:54:25 PM
     */
    public class TestWinMessage
    {
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args)
    	{
    		WinMessage wm = new WinMessage();
    		wm.showMsgBox("MC Hotdog,哈狗帮!");
    	}
    }
    
  7. ok,这下就完成了从java程序中调用win32 API弹出windows原生的窗口了 。

Leave a Reply

Your email address will not be published. Required fields are marked *

You must enable javascript to see captcha here!