首先介绍一下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  本地程序   三者之间数据类型的对应关系,网上随便一百度就行  这儿就不写了

补充,在C++中,使用完传入的数组元素后需要执行以下函数:

    if (in_src_str)
{
env->ReleaseCharArrayElements(in_src_str,src_str_array,);
}
if (in_out_src)
{
env->ReleaseCharArrayElements(in_out_src,out_str_array,);
}
if (in_hex_des_key)
{
env->ReleaseCharArrayElements(in_hex_des_key,hex_des_key_array,);
}
if (in_out_len)
{
env->ReleaseIntArrayElements(in_out_len,src_out_len,);
}

  网上都是这么做的,具体原因不详!

第二版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_hex_des_key, jcharArray in_out_src, jintArray in_out_len)
{ 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 ); //密钥
jint* src_out_len = (env)->GetIntArrayElements(in_out_len, NULL ); //密钥 //Unicode to ascii
char* in_hex_des_key_asiic = UnicodeToAnsi(hex_des_key_array,);
if (!in_hex_des_key_asiic)
{
return NULL;
} char* src_str_array_asiic = UnicodeToAnsi(src_str_array,src_str_array_len);
if (!src_str_array_asiic)
{
return NULL;
} //加密
char* test_key = in_hex_des_key_asiic;
Descrypt(in_if_encrypt,(unsigned char *)src_str_array_asiic,
in_src_len,(unsigned char *)out_str_array,
(int&)*src_out_len,test_key); //将密文out_str_array 转为 jcharArray 赋值给ret_array 并返回
int len = strlen((char *)out_str_array); //加密后长度
jcharArray ret_array = env->NewCharArray(len); //返回数组 jchar *pArray ;
pArray = (jchar*)calloc(len, sizeof(jchar));
int i=;
for(i = ; i < len; i++)
{
*(pArray + i) = *((unsigned char *)out_str_array + i);
} env->SetCharArrayRegion(ret_array,,len,pArray);
free(pArray); //释放内存 if (in_hex_des_key_asiic)
{
delete[] in_hex_des_key_asiic;
in_hex_des_key_asiic = NULL;
} if (src_str_array_asiic)
{
delete[] src_str_array_asiic;
src_str_array_asiic = NULL;
} if (in_src_str)
{
env->ReleaseCharArrayElements(in_src_str,src_str_array,);
}
if (in_out_src)
{
env->ReleaseCharArrayElements(in_out_src,out_str_array,);
}
if (in_hex_des_key)
{
env->ReleaseCharArrayElements(in_hex_des_key,hex_des_key_array,);
}
if (in_out_len)
{
env->ReleaseIntArrayElements(in_out_len,src_out_len,);
} return ret_array; } //将宽字节wchar_t*转化为单字节char*
char* UnicodeToAnsi( const wchar_t* szStr ,int len)
{
char* ret_data = NULL;
int nLen = WideCharToMultiByte( CP_ACP, , szStr, len, NULL, , NULL, NULL );
if (nLen == )
{
return NULL;
}
char* pResult = new char[nLen];
WideCharToMultiByte( CP_ACP, , szStr, -, pResult, nLen, NULL, NULL ); ret_data = new char[nLen+];
memset(ret_data, , nLen+);
strncpy(ret_data, pResult, len);
ret_data[len] = '\0'; if (pResult)
{
delete [] pResult;
} return ret_data;
}

C++

[JNI] Java 调用 C++ dll的更多相关文章

  1. paip.java 调用c++ dll so总结

    paip.java 调用c++ dll so总结 ///////JNA (这个ms sun 的) 我目前正做着一个相关的项目,说白了JNA就是JNI的替代品,以前用JNI需要编译一层中间库,现在JNA ...

  2. Java调用第三方dll文件的使用方法 System.load()或System.loadLibrary()

    Java调用第三方dll文件的使用方法 public class OtherAdapter { static { //System.loadLibrary("Connector") ...

  3. 巧用C#做中间语言 实现Java调用.net DLL

    本文将详细为大家介绍一个java调用.net DLL的方法,以实现特殊的客户的特殊要求:“在Java项目中必须使用其提供的用.net写的DLL加密机制!” 环境与工具: ◆.net framework ...

  4. cocos2d 中使用jni Java 调用 C++ 方法

    1.首先是LoadLibrary cocos2d中的C++代码会编译成一个.so文件.放在安卓文件夹下的libs/armeabi 下,然后java会load进来,这步我们不用做了,由于cocos2d已 ...

  5. java调用C++ DLL库方法

    最近一个项目要开发网页端人脸识别项目,人脸识别的算法已经写好,是C++版,但是网页端要求使用Java后台,这就涉及到Java调用DLL的问题.经过查找,实现了一个简单的例子. 1.第一步,先在Java ...

  6. java调用c++ dll出现中文乱码

    近期的开发用到了使用java调用本机动态连接库的功能,将文件路径通过java调用C++代码对文件进行操作. 在调用中假设路径中包括有中文字符就会出现故障.程序执行就会中止. 以下用一个小样例,来说明记 ...

  7. java调用c#dll文件配置

    1 在强大的c#语言和java语言之间,二者难免会因为某些特殊的要求会相互调用. 下面就以java调用c#的dll为例做详细介绍 1  在vs中的环境设置如下图,图片中程序仅作为讲解程序,在项目编译成 ...

  8. Java调用C# DLL

    由于项目需要,利用了短信猫,但是一个短信猫会加载多个串口,而只需要其AT口,通过java代码,获取其AT口对应的串口号比较困难,于是通过C#获取,这里直接调用C#生成的DLL,但java不能直接调用C ...

  9. JAVA调用动态链接库(dll)

        菜鸡爬坑 基础知识  因为某个东西的keygen我只会在win下生成!! 所以只能出此下策!!之前一直是android下用jni调用so文件,现在试下java在win平台下调用dll 首先还是 ...

随机推荐

  1. POJ 3279 Fliptile[二进制状压DP]

    题目链接[http://poj.org/problem?id=3279] 题意:给出一个大小为M*N(1 ≤ M ≤ 15; 1 ≤ N ≤ 15) 的图,图中每个格子代表一个灯泡,mp[i][j] ...

  2. 在Dll中创建对话框并调用

    1.第一步创建一“MFC AppWizard (dll)”工程,接下来选择“Regular Dll using shared MFC DLL”,点击“Finish”. 2.添加一对话框资源到工程中,从 ...

  3. hdu_2111_Saving HDU(贪心)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2111 题意:给你n个物品的单位体积价值和体积,求装满容量v的背包的最大价值. 题解:乍一看还以为是背包 ...

  4. flashbuilder mx组件 MenuBar

    来源:http://www.cuplayer.com/player/PlayerCode/Flex/2013/0118661.html <fx:Script> <![CDATA[ i ...

  5. Linux启动流程详解【转载】

    在BIOS阶段,计算机的行为基本上被写死了,可以做的事情并不多:一般就是通电.BIOS.主引导记录.操作系统这四步.所以我们一般认为加载内核是linux启动流程的第一步. 第一步.加载内核 操作系统接 ...

  6. linux服务器无法显示tomcat详细错误信息

    严重: One or more listeners failed to start. Full details will be found in the appropriate container l ...

  7. hosts.deny 和hosts.allow 配置不生效

    需求:需要用hosts.deny限制用户通过ssh登录 在/etc/hosts.deny中加入 sshd: all 在/etc/hosts.allow中加入 sshd:all #拒绝所有的ip链接ss ...

  8. launchMode传递参数注意startActivityForResult

    Activity1 到Activity2 用startActivityForResult 如果Activity2的launchMode为 singleInstance 和 singleTask 都会启 ...

  9. CGRect相关工具函数

    NSStringFromCGRect(aCGRect): CGRectFromString(aString):如果把视图的框架以字符串的形式放在NSUserDefaults里面,那么该方法可以将其转回 ...

  10. UITabBarItem's appearance

    1.我们知道,用tabBarController创建出来默认的tabBar似这个样子滴... -----------------我是图片分割线----------------------------- ...