Android系统中Java层函数需要访问Native层函数的话,需要通过Jni,下面通过一个示例来演示windows环境下,在java中调用C库函数。
1、编写java代码。在java层写好类和函数,例如HelloJNI.java:
class HelloJNI {
// 本地方法声明
native void printHello();
native void printString(String str);
// 加载库
static {
System.loadLibrary("hellojni");
}
public static void main(String args[]) {
HelloJNI myJNI = new HelloJNI();
// 调用本地方法(实际调用的是使用C语言编写的JNI本地函数)
myJNI.printHello();
myJNI.printString("Hello World from printString fun");
}
}
2、 编译java代码,在cmd命令行中使用javac命令编译上面的HelloJNI.java文件,生成HelloJNI.class文件: javac -encoding uft-8 HelloJNI.java
在当前目录下就有了.java文件和.class文件了。
3、生成C语言的头文件:我们这里使用的是javah命令来生成所需要的C语言的头文件HelloJNI.h。在cmd控制台中输入javah HelloJNI命令。生成的头文件HelloJNI.h如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloJNI */
#ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloJNI
* Method: printHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloJNI_printHello
(JNIEnv *, jobject);
/*
* Class: HelloJNI
* Method: printString
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_HelloJNI_printString
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
这里面有在java文件中声明的两个函数的原型。不要随意修改,在后面使用。
ps:这里主要是注册java在JIN层的函数,一般有静态和动态两种注册方法,这里采用的就是静态注册方法。
4、编写C/C++代码:
在hellojni.c文件中实现在头文件HelloJNI.h中声明的函数,注意补齐形参,并包含头文件:
#include "HelloJNI.h"
#include <stdio.h>
/*
* Class: HelloJNI
* Method: printHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloJNI_printHello
(JNIEnv *env, jobject obj){
printf("Hello World!\n");
return;
}
/*
* Class: HelloJNI
* Method: printString
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_HelloJNI_printString
(JNIEnv *env, jobject obj, jstring string){
const char *str = (*env)->GetStringUTFChars(env,string,0);
printf("%s!\n",str);
return;
}
5、生成共享库.dll文件:
5.1、首先将jdk目录下的jni.h(C:\Program Files\Java\jdk1.8.0_102\include\jni.h)和jni_md.h(C:\Program Files\Java\jdk1.8.0_102\include\win32\jni_md.h)这两个文件拷贝到vs的include(D:\Microsoft Visual Studio 11.0\VC\include)目录下。
5.2、将3和4中的.c文件和.h文件拷贝到D:\Microsoft Visual Studio 11.0\VC目录中,供编译使用。
5.3、在开始菜单中打开Microsoft Visual Studio 2012->Visual Studio Tools->VS2012 x64 兼容工具命令提示(根据自己平台选择32位还是64位,这里是选择的64位的)。在命令行中输入如下命令:
cl -I"<C:\Program Files\Java\jdk1.8.0_102>\include" -I"<C:\Program Files\Java\jdk1.8.0_102>\include\win32" -LD hellojni.c -Fehellojni.dll
ps:各种参数的含义:
cl:visual c++编译命令;
-I<dir>:添加要检索头文件的目录路径,这里需要包含jni.h和jni_md.h这两个头文件。虽然在上述命令中已经包含着两个头文件的目录路径,但还是存在无法找到头文件的情况,所以特地在4.1中将这两个头文件手动添加到了……\VC\include目录下。
-LD:创建dll文件;
-Fe<文件名>:指定编译结果文件名称;
6、运行java程序:将5中生成的hellojni.dll文件拷贝到java文件目录下,然后在cmd命令行中输入java HelloJNI运行java程序。根据书写的程序内容,应该在控制台中返回:
Hello World!
Hello World from printString fun!
至此就完成了在java中调用C库函数!