转 J2SE:JNI:JAVA调用已经存在的动态连接库(dll)

来源:互联网 发布:鱼眼校正软件 编辑:程序博客网 时间:2024/05/12 15:51
   有时候吧,一个项目不是由单一的某种语言构成的,所以避免不了语言与语言之间的协作关系。
比如:这时你的项目部分是用JAVA编写的,你需要对数据进行加密与解密的操作,一般来说你会用JAVA实现一个加密算法。不过呢,现在你手头上有个非JAVA的组件可以用,比如DLL,考虑到效率上的问题你使用这个DLL更好些。这时候你就得使用JNI(JAVA NATIVE INTERFACE)—JAVA 原生接口。

        这样我们从一个JAVA调用一个存在的DLL例子入手吧。

                         DES.dll  调用接口如下:

1、加密
I=Encrypt(对象,密文, 明文, 密钥)
I=1时加密成功;I=0时加密失败 ;I为整型变量
函数:int   Encrypt(void * objptr,char* OutBuffer,LPSTR DataInBuffer,LPSTR KeyInBuffer)

输入参数:

CString DataInBuffer,要加密的明文
CString KeyInBuffer 加密密钥
       要求:8-16个字符,(实际范围0-16字符)

输出参数:

char* OutBuffer, 加密后的密文
                     格式:(明文字符数/8+1)*16
2、解密
I=Decrypt(对象,原文,密文, 密钥)
I=1时加密成功;I=0时加密失败 ;I为整型变量
函数:int Decrypt(void * objptr,char * OutBuffer,LPSTR DataInBuffer,LPSTR KeyInBuffer)

输入参数:

CString DataInBuffer,要解密的密文
       无格式要求
CString KeyInBuffer 解密密钥
要求:8-16个字符,(实际范围0-16字符)

输出参数:

char* OutBuffer, 解密后的明文
                      格式:原文字符串
3、对象
void * CreateDES_Dll()

 




        首先,实现一个JAVA代码,声明原生函数和参数。

package com.daxiannetwork.util;

public class JDES {
    /**
     * Kaede
     */
    static{
          
        System.loadLibrary("com_daxiannetwork_util_JDES");
        
    }
    public native String Decrypt(String cryptograph,String key);
    //声明的原生函数Decrypt,用于解密
    public native String Encrypt(String proclaim,String key);
    //声明的原生函数Encrypt,用于加密

    public static void main(String[] args) {

        JDES jdes=new JDES();
        
        String a=jdes.Encrypt("123","1")
        //1为密钥
        String b=jdes.Encrypt(a,"1");

        System.out.println(a+":"+b);

            }
}

                       然后,编译(这里不叙述),生成JDES.class。
                       接下来,用javah.exe生成C的头文件。
                      这个必须说一下,由于我们这个类包含在com.daxiannetwork.util中。
                        javah -jni -d D:/eclipse/workspace/GUI/com/daxiannetwork/util com.daxiannetworkt.util.JDES

                        在这个目录下D:/eclipse/workspace/GUI/com/daxiannetwork/util 有一个com_daxiannetwork_util_JDES.h
这个就是我们要得到的头文件。
                           
#include "jni.h"
#ifndef _Included_com_daxiannetwork_util_JDES
#define _Included_com_daxiannetwork_util_JDES
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_daxiannetwork_util_JDES
 * Method:    Decrypt
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_daxiannetwork_util_JDES_Decrypt
  (JNIEnv *, jobject, jstring, jstring);
/*
 * Class:     com_daxiannetwork_util_JDES
 * Method:    Encrypt
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_daxiannetwork_util_JDES_Encrypt
  (JNIEnv *, jobject, jstring, jstring);
#ifdef __cplusplus
}
#endif
#endif

看看,跟正常的C头文件有什么差别,
JNIEXPORT jstring JNICALL Java_com_daxiannetwork_util_JDES_Encrypt (JNIEnv *, jobject, jstring, jstring);
JNIEXPORT,JNICALL这是宏,将被展开为平台专有的指令。JNIEnv , jobject, jstring, jstring 都是
JNI定义的数据类型。
Java_com_daxiannetwork_util_JDES_Encrypt 这个是函数名,所有的原生函数都以Java作为标识,后面是包名方法名。呵呵,这样使得C++代码必须实现这样的方法,可是原有的dll函数不是这样的,
所以我采用java—>yourDLL—>otherDLL。

现在我们来实现自己的DLL吧!
用VC++创建一个com_daxiannetwork_util_JDES MFC 动态连接库的项目(由于已经存在的DLL是用MFC实现的),然后将%JAVA_HOME%/include与%JAVA_HOME%/include/win32下的.h文件加入到项目中,
接着,修改VC++项目生成的com_daxiannetwork_util_JDES.h,将JAVAH生成的.h文件用记事本打开、复制
所有内容,粘贴到VC++项目生成的com_daxiannetwork_util_JDES.h,最前面。
实现这个本地函数,打开com_daxiannetwork_util_JDES.cpp,加入以下代码,如下。


#include "com_daxiannetwork_util_JDES.h"

//将调用的DLL头文件
#include "DES_DLL_I.h"
JNIEXPORT jstring JNICALL Java_com_daxiannetwork_util_JDES_Decrypt
   (JNIEnv *env, jobject obj, jstring cryptograph,jstring key) {
    
 const char *T_cryptograph = env->GetStringUTFChars(cryptograph, 0);
    
 const char *T_key = env->GetStringUTFChars(key, 0);
    void * objptr = CreateDES_Dll();
 char * OutputStr = new char[1000];
    char mingwen[1000];
 int result = Decrypt(objptr,OutputStr,T_cryptograph,T_key);
   
    strcpy(mingwen,OutputStr);
    //告诉VM本地代码不在有权使用UTF
 env->ReleaseStringUTFChars(cryptograph, T_cryptograph);
    env->ReleaseStringUTFChars(key, T_key);
   
 delete [] OutputStr;
 return env->NewStringUTF(mingwen);
 }

//加密
JNIEXPORT jstring JNICALL Java_com_daxiannetwork_util_JDES_Encrypt
   (JNIEnv *env, jobject obj, jstring proclaim,jstring key) {
   
 const char *T_proclaim = env->GetStringUTFChars(proclaim, 0);
    
 const char *T_key = env->GetStringUTFChars(key, 0);
    void * objptr = CreateDES_Dll();//调用other dll 中的一个方法。
 char * OutputStr = new char[1000];
    char miwen[1000];
 int result = Encrypt(objptr,OutputStr,T_proclaim,T_key);//调用other dll 中的一个方法。
    
    strcpy(miwen,OutputStr);

 env->ReleaseStringUTFChars(proclaim, T_proclaim);
 env->ReleaseStringUTFChars(key, T_key);
   
 delete [] OutputStr;
  return env->NewStringUTF(miwen);
 }

编译,生成com_daxiannetwork_util_JDES.dll,然后将这两个DLL注册到PATH中。
 运行程序。

呵呵,这个介绍了调用第3方的DLL,但是不适合出学者。其实都是一样的,就是JDES.class与com_daxiannetwork_util_JDES.dll沟通。

将紫色部分去掉就是只有JDES.class与com_daxiannetwork_util_JDES.dll沟通了,呵呵,就是直来直去。

呵呵,关于JNI更详细的请见:
http://java.sun.com/j2se/1.3/docs/guide/jni/spec/jniTOC.doc.html

JNI调用已经存在的dll,呵呵 文章写的不好。见谅!!
有问题这里问就好了,我经常来的。


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=253333
原创粉丝点击