java调用dll char_Java通过JNI调用dll详细过程(转)

最近项目有这样一个需求,在已有的CS软件中添加一个链接,将当前登录用户的用户名加密后放在url地址中,在BS的login方法里通过解密判断,如果为合法用户则无需再次登录直接进入平台,CS软件方提供了一个加密解密的dll文件,我们需要在action中通过该dll解密,那么就涉及到java调用dll的问题。

首先我选择了JNI方式(因为网上说的另两种方式Jawin, Jacob更不会),大体流程如下:

1、写一个java的class,在类里声明所调用的库名称和需要使用的函数(注意:需要对方法做本地声明,关键字为native。且只需要声明,而不需要具体实现)

packagecom;public classjavacall

{static{

System.loadLibrary("htgsjencrypt");

}public native static String DecodeString(char[] szSrc);public native static String EncodeString(char[] szSrc);private static void printCharArray(char[] content)

{

String temp=newString(content);

System.out.println(temp);

}public static voidmain(String[] args)

{

String s="123";char[] src=new char[100];

src=s.toCharArray();

String encode="";

printCharArray(src);

encode=javacall.EncodeString(src);

System.out.println("encode="+encode);

String decode="";

src=encode.toCharArray();

decode=javacall.DecodeString(src);

System.out.println("decode="+decode);

}

}

这个地方需要提一下,新建这个class时最好不要建在默认包中,将来对这个工程打包后,在引用的工程中无法找到默认包中的class(也许是我写的不对,不过写在默认包中确实会带来不必要的麻烦)

2、对于以上编译好的class文件通过使用javah命令生成头文件javacall.h,这个文件需要被C++程序调用来生成所需的库文件

/*DO NOT EDIT THIS FILE - it is machine generated*/#include"jni.h"

/*Header for class com_javacall*/#ifndef _Included_com_javacall

#define _Included_com_javacall

#ifdef __cplusplus

extern"C"{

#endif/** Class: com_javacall

* Method: DecodeString

* Signature: ([C)Ljava/lang/String;*/JNIEXPORT jstring JNICALL Java_com_javacall_DecodeString

(JNIEnv*, jclass, jcharArray);/** Class: com_javacall

* Method: EncodeString

* Signature: ([C)Ljava/lang/String;*/JNIEXPORT jstring JNICALL Java_com_javacall_EncodeString

(JNIEnv*, jclass, jcharArray);

#ifdef __cplusplus

}

#endif

#endif

这里需要提到一点,默认生成的头文件中写的是

#include

在C++的calss中引用时编译报错找不到jni.h,可以去jdk安装包的include文件夹中拷贝jni.h、jni_md.h、jawt_md.h三个文件到程序目录,这时再编译可能还报找不到jni.h的错误,可以将#include 改为#include "jni.h",因为前者是引用系统头文件的写法

3、在VC中新建一个库文件htgsjencrypt,在新建的class文件中实现java头文件中声明的两个加密解密方法,因为第三方没有提供.lib文件,也没有.h文件,那么只能用动态使用链接库的方式来调用dll了,具体代码如下:

#include "gsjencrypt.h"#include"com_javacall.h"#include"windows.h"#include

//

//Construction/Destruction

//

gsjencrypt::gsjencrypt()

{

}

gsjencrypt::~gsjencrypt()

{

}

typedefint (WINAPI *FDecodeString)(char szSrc[100], char szDest[100]);

typedefint (WINAPI *FEncodeString)(char szSrc[100], char szDest[100]);

JNIEXPORT jstring JNICALL Java_com_javacall_EncodeString(JNIEnv*env, jclass jobject, jcharArray src)

{

HINSTANCE hDLL;

hDLL=LoadLibrary("gsjencrypt.dll");//加载动态链接库gsjencrypt.dll文件;

if(hDLL==NULL)return 0;

FEncodeString encodeString=(FEncodeString)GetProcAddress(hDLL,"EncodeString");

jsize size= (env)->GetArrayLength(src);

jchar* arrayBody = (env)->GetCharArrayElements(src,0);//char * csrc=(char *)arrayBody;

char csrctemp[100]="";int k=0;while(size!=0)

{

csrctemp[k]=*arrayBody;*arrayBody++;

size--;

k++;

}char cdesttemp[100]="";

encodeString(csrctemp,cdesttemp);

(env)->ReleaseCharArrayElements(src,arrayBody,0);return (env)->NewStringUTF(cdesttemp);

}

JNIEXPORT jstring JNICALL Java_com_javacall_DecodeString(JNIEnv*env, jclass jobject, jcharArray src)

{

HINSTANCE hDLL;

hDLL=LoadLibrary("gsjencrypt.dll");//加载动态链接库gsjencrypt.dll文件;

if(hDLL==NULL)return 0;

FDecodeString decodeString=(FDecodeString)GetProcAddress(hDLL,"DecodeString");

jsize size= (env)->GetArrayLength(src);

jchar* arrayBody = (env)->GetCharArrayElements(src,0);char * csrc=(char *)arrayBody;char csrctemp[100]="";int k=0;while(size!=0)

{

csrctemp[k]=*arrayBody;*arrayBody++;

size--;

k++;

}//arrayBody=(env)->GetCharArrayElements(dest,0);//char * cdest=(char *)arrayBody;

char cdesttemp[100]="";

decodeString(csrctemp,cdesttemp);

(env)->ReleaseCharArrayElements(src,arrayBody,0);return (env)->NewStringUTF(cdesttemp);

}

这里需要注意的是

typedef int (WINAPI *FDecodeString)(char szSrc[100], char szDest[100]);

typedefint (WINAPI *FEncodeString)(char szSrc[100], char szDest[100]);

以上两个方法是原始dll中提供给外界调用的函数接口,声明时一定要记得加WINAPI,否则调用时始终报错。

4、最后将第三方提供的gsjencrypt.dll和新生成的htgsjencrypt.dll同时拷贝到java.library.path里(jdk或者jre的bin文件中),然后将最开始写的java程序打包即可被别的工程调用。

记录一下最难解决的问题,就是不知道怎样在c++中返回给java解密后的串,因为总是想把指针的概念与java中的某个byte数组或者char数组关联起来,始终不能成功,最后尝试使用NewStringUTF才解决问题,哎,C++已经六年没用过了,真是费劲啊

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值