前言:前段时间在CSDN的C++社区遇到一个需要封装考勤机接口的动态库给JAVA调用的帖子,勾起了我对JAVA的无限怀念。在此,我想把这项技术简单再介绍一下。
一、关于Java Native Interface (JNI)
JNI是JAVA本地编程接口,属于JDK的一部分。它允许JAVA能够操作本地API或由其他语言编写的动态库。不过当你使用这项技术的时候,需要考虑JAVA的可移植性。
二、编写一个简单的JNI程序
1、编写一个JAVA程序
//声明本地方法,以native为关键字
public native void displayHelloWorld();
static
{
//加载本地方法所在的动态库
System.loadLibrary("HelloWorld");
}
public static void main(String[] args)
{
new HelloWorld().displayHelloWorld();
}
}
重点部分: a)本地方法以native为关键字声明 b)加载动态库
2、编译源程序
cmd > javac HelloWorld.java
3、创建.h文件我们需要从HelloWorld.class文件中生成对应的.h文件,以便在C/C++编写代码。
cmd>javah -jni HelloWorld
生成的文件(HelloWorld.h)长这个样子:
/* * Class: HelloWorld * Method: displayHelloWorld * Signature: ()V */
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);
#ifdef __cplusplus}
#endif
#endif
4、对应HelloWorld.h文件创建一个.c文件,实现部分在里面编写
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
{
printf("Hello world!/n");
return;
}
5、编译该.c文件,生成dll
cmd >cl /IC:/j2sdk1.4.2_08/include /IC:/j2sdk1.4.2_08/include/win32 /LD HelloWorld.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
HelloWorld.c
Microsoft (R) Incremental Linker Version 8.00.50727.42
Copyright (C) Microsoft Corporation. All rights reserved.
/out:HelloWorld.dll
/dll
/implib:HelloWorld.libHelloWorld.obj
正在创建库 HelloWorld.lib 和对象 HelloWorld.exp
其中:/I 表示在目录中搜索包含文件 /LD 代表创建动态链接库
6、运行java程序,看效果
cmd >java HelloWorld
Hello world!
二、java 与 C/C++之间的类型匹配像一些基本类型,如:int,float,long 等等。
java 和 C/C++是可以直接匹配的,在编写过程中不需要进行而外的转换。这些基本类型包括如下:
boolean jboolean 8, unsigned
byte jbyte 8
char jchar 16,
unsigned short jshort 16
int jint 32
long jlong 64
float jfloat 32
double jdouble 64
void void n/a
但是对于String之类对象就必须做一些额外的处理
例子:String 对象的接收与返回
static
{
//加载本地方法所在的动态库
System.loadLibrary("HelloWorld");
}
public static void main(String[] args)
{
System.out.println(welcome("Yzl"));
}
}
1、编译生成.class文件
cmd > javac HelloWorld.java
2、创建.h文件
cmd > javah -jni HelloWorld
3、编写HelloWorld.c文件
JNIEXPORT jstring JNICALL Java_HelloWorld_welcome(JNIEnv *env, jclass cls, jstring name)
{
char buf[128] = "Welcome ";
//获取接受进来的jstring
const char *str = (*env)->GetStringUTFChars(env, name, 0);
strcat(buf,str);
//释放该string
(*env)->ReleaseStringUTFChars(env, name, str);
//生成新的jstring返回回去
return (*env)->NewStringUTF(env, buf);
}
4、编译HelloWorld.c文件
cmd > cl /IC:/j2sdk1.4.2_08/include /IC:/j2sdk1.4.2_08/include/win32 /LD HelloWorld.c
5、运行HelloWorld.class文件
cmd > java HelloWorld
Welcome Yzl
三、java 和 C/C++ 的数组类型匹配
1、创建java文件
static
{
//加载本地方法所在的动态库
System.loadLibrary("HelloWorld");
}
public static void main(String[] args)
{
int[] arr = new int[5];
//初始化
for(int i = 0; i < arr.length; i ++) arr[i] = i + 1;
System.out.println("sum(5)=" + sum(arr));
}
}
2、编译生成.class文件
cmd > javac HelloWorld.java
3、创建HelloWorld.h文件
cmd > javah -jni HelloWorld
4、创建HelloWorld.c文件
JNIEXPORT jint JNICALL Java_HelloWorld_sum(JNIEnv *env, jclass cls, jintArray arr)
{
int i = 0,sum = 0;
//获取该数组的长度
jsize len = (*env)->GetArrayLength(env, arr);
//获取该数组的首地址
jint *body = (*env)->GetIntArrayElements(env, arr, 0);
//计算和
for(; i < len; i ++) sum += body[i];
//释放数组
(*env)->ReleaseIntArrayElements(env, arr, body, 0);
//返回结果
return sum;
}
5、编译HelloWorld.c文件
cmd > cl /IC:/j2sdk1.4.2_08/include /IC:/j2sdk1.4.2_08/include/win32 /LD HelloWorld.c
6、运行HelloWorld.class文件
cmd > java HelloWorldsum(5)=15
四、C/C++ 调用java中的方法
CSDN blog编辑器太烂了。不写了,略!
五、C/C++ 访问java中的成员
CSDN blog编辑器太烂了。不写了,略!
六、其他相关资源参阅:<<The java tutorialTM 1.42>>
小样的,这点破文排版花了我7遍,我日! 再不行不管了。。