标签:
首先介绍一下JNI吧!
JNI 是Java提供的一个用于调用本地接口的接口层,位于Java代码 和 本地代码之间的一层;主要功能是 数据类型的转换,还有就是通过这一层来调用本地代码!
下面就说说Java 调用 C++ dll是怎么实现的吧!
1、首先用Java代码制作接口层
package NEU.SOFT; public class NEUdll { public NEUdll() { } //供Java调用的本地代码 public native char[] Descrypt(boolean if_encrypt, char[] src_str_out,int src_len,char[] out_src_out, int out_len_out,char[] hex_des_key_out); }
这样就可以在Java代码中调用Descrypt 这个方法了;记住 关键是 声明本地函数 关键字native
下面是调用Descrypt 方法的Java代码(红色是关键)
import NEU.SOFT.NEUdll; public class helpMain { public static void main(String[] args) { System.out.println("开始啦~~~~!!"); //加载NEUSOFT.DLL 位于 system32下面 System.loadLibrary("NEUSOFT"); NEUdll neu = new NEUdll(); String src_str = "abcd"; char[] src = {‘a‘,‘b‘,‘c‘,‘d‘}; char[] key = {‘N‘,‘E‘,‘U‘,‘S‘,‘O‘,‘F‘,‘T‘,‘2‘}; char[] out_data = new char[10000]; char[] getData = neu.Descrypt(true, src, 4, out_data, 10000, key); // String data = String.valueOf(getData); System.out.println("结束啦~~~~!!" + data); } }
接下来是要利用C++代码,编写DLL
既然是Java调用,自然是调用Java的类,因此需要将“接口层”那段代码变成.h文件 javah .class文件的包名类文件名(不带后缀) eg:javah NEU.SOFT.NEUdll (是class文件 不是 Java源文件)
现在就生成了一个 NEU.SOFT.NEUdll.h的文件
新建一个工程 选择 win32 Dynamic link library,然后将刚刚生成的.h头文件放到工程目录下,转到新建的项目中 添加代码 #include NEU.SOFT.NEUdll.h 然后打开NEU.SOFT.NEUdll.h 将里面的#include<jni.h> 改为 #include"jni.h" 在%Javahome% 的目录下 找到
#include "jni.h"
#include "jni_md.h"
这两个.h文件 也放到新建的DLL工程目录下。
打开刚刚生成的.h文件 可以看到里面有一个函数 样子大概和java接口层中的样子差不多,
JNIEXPORT jcharArray JNICALL Java_NEU_SOFT_NEUdll_Descrypt
(JNIEnv *, jobject, jboolean, jcharArray, jint, jcharArray, jint, jcharArray);
现在就编写他的函数体就行了(在#include NEU.SOFT.NEUdll.h 的文件中编写),C++代码 如下:
JNIEXPORT jcharArray JNICALL Java_NEU_SOFT_NEUdll_Descrypt (JNIEnv* env, jobject obj, jboolean in_if_encrypt,jcharArray in_src_str, jint in_src_len, jcharArray in_out_src, jint in_out_len,jcharArray in_hex_des_key) { jchar* src_str_array = (env)->GetCharArrayElements(in_src_str, NULL ); //明文 int src_str_array_len = (env)->GetArrayLength(in_src_str); //明文长度 jchar* out_str_array = (env)->GetCharArrayElements(in_out_src, NULL ); //密文 jchar* hex_des_key_array = (env)->GetCharArrayElements(in_hex_des_key, NULL ); //密钥 //对输入的长度进行类型转换 int int_in_out_len = (int)in_out_len; int& replace_in_out_len = int_in_out_len; //Unicode to ascii char* in_hex_des_key_asiic = UnicodeToAnsi(hex_des_key_array,8); char* src_str_array_asiic = UnicodeToAnsi(src_str_array,src_str_array_len); //加密 char* test_key = "NEUSOFT2"; Descrypt(in_if_encrypt,(unsigned char *)src_str_array_asiic,in_src_len,(unsigned char *)out_str_array, replace_in_out_len,test_key); int len = strlen((char *)out_str_array); //加密后长度 jcharArray ret_array = env->NewCharArray(len); //返回数组 //将密文out_str_array 转为 jcharArray 赋值给ret_array 并返回 jchar *pArray ; pArray = (jchar*)calloc(len, sizeof(jchar)); int i=0; for(i = 0; i < len; i++) { *(pArray + i) = *((unsigned char *)out_str_array + i); } env->SetCharArrayRegion(ret_array,0,len,pArray); free(pArray); //释放内存 return ret_array; }
编写完之后,F7 编译,就会生成DLL文件,放到system32 目录下,就可以像第二段代码中那也调用了。
步骤小结:1、用Java编写类
2、使用javah命令将这个类变为.h头文件
3、在C++工程中,#include 这个头文件(记住修改<> 为 "",还要#include 另外两个)
4、用C++代码 完成.h头文件中函数内容的编写
5、生成DLL文件,放到 system32下面
6、Java代码加载这个文件 产生一个对象,通过这个对象调用里面的方法就行。
杂记:在生成的.h文件中 函数声明中有JNIEnv* env, jobject obj这样两个参数 其中第一个 作用很大
可以通过它去获取数组的元素 长度 为数组赋值等很多操作。
还有就是Java jni 本地程序 三者之间数据类型的对应关系,网上随便一百度就行 这儿就不写了
标签:
原文地址:http://www.cnblogs.com/tengpan-cn/p/4782021.html