黑马程序员-java——JNI
来源:互联网 发布:小受坐轮椅卖淘宝 编辑:程序博客网 时间:2024/06/08 00:41
---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------
1、写一个java的class,在类里声明所调用的库名称和需要使用的函数(注意:需要对方法做本地声明,关键字为native。且只需要声明,而不需要具体实现)
01
package
com;
02
public
class
javacall
03
{
04
static
05
{
06
System.loadLibrary(
"htgsjencrypt"
);
07
}
08
09
public
native
static
String DecodeString(
char
[] szSrc);
10
public
native
static
String EncodeString(
char
[] szSrc);
11
12
private
static
void
printCharArray(
char
[] content)
13
{
14
String temp=
new
String(content);
15
System.out.println(temp);
16
}
17
public
static
void
main(String[] args)
18
{
19
String s=
"123"
;
20
char
[] src=
new
char
[
100
];
21
src=s.toCharArray();
22
String encode=
""
;
23
printCharArray(src);
24
encode=javacall.EncodeString(src);
25
System.out.println(
"encode="
+encode);
26
String decode=
""
;
27
src=encode.toCharArray();
28
decode=javacall.DecodeString(src);
29
System.out.println(
"decode="
+decode);
30
31
}
32
}
这个地方需要提一下,新建这个class时最好不要建在默认包中,将来对这个工程打包后,在引用的工程中无法找到默认包中的class(也许是我写的不对,不过写在默认包中确实会带来不必要的麻烦)
2、对于以上编译好的class文件通过使用javah命令生成头文件javacall.h,这个文件需要被C++程序调用来生成所需的库文件
01
/* DO NOT EDIT THIS FILE - it is machine generated */
02
#include "jni.h"
03
/* Header for class com_javacall */
04
05
#ifndef _Included_com_javacall
06
#define _Included_com_javacall
07
#ifdef __cplusplus
08
extern
"C"
{
09
#endif
10
/*
11
* Class: com_javacall
12
* Method: DecodeString
13
* Signature: ([C)Ljava/lang/String;
14
*/
15
JNIEXPORT jstring JNICALL Java_com_javacall_DecodeString
16
(JNIEnv *, jclass, jcharArray);
17
18
/*
19
* Class: com_javacall
20
* Method: EncodeString
21
* Signature: ([C)Ljava/lang/String;
22
*/
23
JNIEXPORT jstring JNICALL Java_com_javacall_EncodeString
24
(JNIEnv *, jclass, jcharArray);
25
26
#ifdef __cplusplus
27
}
28
#endif
29
#endif
这里需要提到一点,默认生成的头文件中写的是
#include <jni.h>
在C++的calss中引用时编译报错找不到jni.h,可以去jdk安装包的include文件夹中拷贝jni.h、jni_md.h、jawt_md.h三个文件到程序目录,这时再编译可能还报找不到jni.h的错误,可以将#include <jni.h>改为#include "jni.h",因为前者是引用系统头文件的写法
3、在VC中新建一个库文件htgsjencrypt,在新建的class文件中实现java头文件中声明的两个加密解密方法,因为第三方没有提供.lib文件,也没有.h文件,那么只能用动态使用链接库的方式来调用dll了,具体代码如下:
01
#include "gsjencrypt.h"
02
#include "com_javacall.h"
03
#include "windows.h"
04
#include <iostream>
05
//////////////////////////////////////////////////////////////////////
06
// Construction/Destruction
07
//////////////////////////////////////////////////////////////////////
08
09
gsjencrypt::gsjencrypt()
10
{
11
12
}
13
14
gsjencrypt::~gsjencrypt()
15
{
16
17
}
18
typedef
int
(WINAPI *FDecodeString)(
char
szSrc[100],
char
szDest[100]);
19
typedef
int
(WINAPI *FEncodeString)(
char
szSrc[100],
char
szDest[100]);
20
21
JNIEXPORT jstring JNICALL Java_com_javacall_EncodeString(JNIEnv * env, jclass jobject, jcharArray src)
22
{
23
HINSTANCE
hDLL;
24
hDLL=LoadLibrary(
"gsjencrypt.dll"
);
//加载动态链接库gsjencrypt.dll文件;
25
if
(hDLL==NULL)
26
return
0;
27
FEncodeString encodeString=(FEncodeString)GetProcAddress(hDLL,
"EncodeString"
);
28
jsize size = (env)->GetArrayLength(src);
29
30
jchar * arrayBody = (env)->GetCharArrayElements(src,0);
31
//char * csrc=(char *)arrayBody;
32
33
char
csrctemp[100]=
""
;
34
int
k=0;
35
while
(size!=0)
36
{
37
csrctemp[k]=*arrayBody;
38
*arrayBody++;
39
size--;
40
k++;
41
}
42
char
cdesttemp[100]=
""
;
43
encodeString(csrctemp,cdesttemp);
44
(env)->ReleaseCharArrayElements(src,arrayBody,0);
45
return
(env)->NewStringUTF(cdesttemp);
46
}
47
JNIEXPORT jstring JNICALL Java_com_javacall_DecodeString(JNIEnv * env, jclass jobject, jcharArray src)
48
{
49
HINSTANCE
hDLL;
50
hDLL=LoadLibrary(
"gsjencrypt.dll"
);
//加载动态链接库gsjencrypt.dll文件;
51
if
(hDLL==NULL)
52
return
0;
53
FDecodeString decodeString=(FDecodeString)GetProcAddress(hDLL,
"DecodeString"
);
54
jsize size = (env)->GetArrayLength(src);
55
jchar * arrayBody = (env)->GetCharArrayElements(src,0);
56
char
* csrc=(
char
*)arrayBody;
57
char
csrctemp[100]=
""
;
58
int
k=0;
59
while
(size!=0)
60
{
61
csrctemp[k]=*arrayBody;
62
*arrayBody++;
63
size--;
64
k++;
65
}
66
//arrayBody=(env)->GetCharArrayElements(dest,0);
67
//char * cdest=(char *)arrayBody;
68
char
cdesttemp[100]=
""
;
69
decodeString(csrctemp,cdesttemp);
70
(env)->ReleaseCharArrayElements(src,arrayBody,0);
71
return
(env)->NewStringUTF(cdesttemp);
72
}
这里需要注意的是
typedef int (WINAPI *FDecodeString)(char szSrc[100], char szDest[100]);typedef int (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才解决问题。
---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------
详细请查看:<a href="http://www.itheima.com" target="blank">www.itheima.com</a>
- 黑马程序员-java——JNI
- 黑马程序员—java总结
- 黑马程序员—java多线程
- 黑马程序员—Java GUI
- 黑马程序员—JAVA多线程
- 黑马程序员—JAVA枚举
- 黑马程序员—JAVA内省
- 黑马程序员—JAVA注解
- 黑马程序员—JAVA泛型
- 黑马程序员—Java 反射
- 黑马程序员—Java概述
- 黑马程序员—Java基础知识
- 黑马程序员—java多线程
- 黑马程序员—JAVA基础
- 黑马程序员—Java多线程
- 黑马程序员—Java泛型
- 黑马程序员—java异常
- 黑马程序员—java API
- Android WifiDisplay分析一:相关Service的启动(转载)
- led驱动_使用次设备号来区别设备
- Java之美[从菜鸟到高手演变]之设计模式
- .NET入门基础教程视频分享
- 数位dp--spoj1182
- 黑马程序员-java——JNI
- The 3n+1
- 天语V9刷机包 Lewa OS V4.1.12 已Root
- JS禁用右键,禁用打印,防止另存为
- Local Search
- linux下启动tomcat的时候提示java.net.UnknownHostException的解决办法
- C/C++ 中的assert()宏 断言机制
- 享受学生给我的精神动力
- Effective Java (3) 使用似有构造器或者枚举强化Singleton属性