(1):编写.java文件,其中c中的函数要用public native static修饰。
(2):编译.java文件为.class文件,使用javah生成.h文件。
(3):按照.h文件中的函数形式在c中实现函数。
(4):生成.dll文件,拷贝到java工程中。
(5):运行java文件。
注意以下几点:
(1)如果java源文件放在包中,一定要在工程目录下使用javah命令。
(2)在编写c函数时,需要把jdk中的include目录添加到编译标志-I后。
(3)在java文件中包含如下一句:static{System.loadLibrary("")},引号中为生成的动态连接库文件,不用加扩展名,系统会自动识别的。
public class HelloDll { //用System.loadLibary加载Hello动态库。 static { System.loadLibrary("Hello"); } //用关键字native声明函数为本地函数 public native static void Display(String Name); /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Display("hello world\n"); } }代码说明:
static { System.loadLibrary("Hello"); }
public native static void Display(String Name);
在java中,提供了javah这个命令来生成本地方法的头文件。使用命令如下:
javah -classpath A -d B -jni C
其中,A是你的.class文件的路径,这样java就可以搜索到这个.class文件。B是将要生成的头文件的存放目录,可以根据需要指定。C是java类名,在这个例子中就是HelloDll。然后就可以在B目录下看到生成的头文件了。
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class HelloDll */ #ifndef _Included_HelloDll #define _Included_HelloDll #ifdef __cplusplus extern "C" { #endif /* * Class: HelloDll * Method: Display * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_HelloDll_Display (JNIEnv *, jclass, jstring); #ifdef __cplusplus } #endif #endif
/* * Class: HelloDll * Method: Display * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_HelloDll_Display (JNIEnv *, jclass, jstring);
#include <iostream> #include "HelloDll.h" /* * Class: HelloDll * Method: Display * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_HelloDll_Display (JNIEnv *env, jclass jthis, jstring data) { jboolean bCopy; const char* cData = env->GetStringUTFChars(data, &bCopy); std::cout << cData << std::endl; env->ReleaseStringUTFChars(data, cData); }
//用System.loadLibary加载Hello动态库。 static { System.loadLibrary("Hello"); }//用关键字native声明函数为本地函数:
public native static void Display(String Name);
生成c++接口文件(头文件)。
在java中,提供了javah这个命令来生成本地方法的头文件。使用命令如下:
javah -classpath A -d B -jni C
其中,A是你的.class文件的路径,这样java就可以搜索到这个.class文件。B是将要生成的头文件的存放目录,可以根据需要指定。C是java类名,在这个例子中就是HelloDll。然后就可以在B目录下看到生成的头文件了。
首先在eclipse中点击下图图标的下拉菜单
然后点击External Tools Configurations
会弹出下面的页面,然后在那3个地方分别填入下图中的命令
其实,这里的操作就是把javah这个可执行程序当做外部工具引入eclipse中来了。调用的时候,eclipse就会执行javah,并且使用预设的arguments,即:
javah -classpath .;./classes -d "${project_loc}“ -jni ${java_type_name}
可以看到,.class文件的搜索目录是当前工作目录和子目录classes(android开发时生成的.class是在classes这个子目录中,所以这里也加了这个目录,如果你不搞android开发,那不加这个目录也没关系)。当前工作目录就是上面设好的${project_loc}/bin,也就是你这个java工程的bin文件夹。这样javah就可以在该目录下找到本地方法的.class文件。-d "${project_loc}"是为了让生成好的.h头文件直接被放置在java工程目录下,便于后续操作。 最后的${java_type_name}是动态的参数,你在生成.h头文件之前先在eclipse中选中本地方法那个java文件,这样java_type_name就自动变成了这个本地方法的名字。
设置好以后,我们来试着生成一下头文件,先在eclipse中选中刚刚定义好的本地方法Example.java,然后点击下图中的位置来调用javah这个外部工具,就可以自动生成头文件了(需要在当前工程中刷新一下才能看到)。
这样设置好以后,将来各位同学在需要生成头文件时,只需写好本地方法的java类,然后鼠标点击一下就能够自动生成头文件了。
生成C++接口实现动态库:
File->New->Project->c/c++->c++ project
在Hello工程点右键 New->Source File
在Hello.cpp文件中加入下列代码:
#include <iostream> #include "HelloDll.h" /* * Class: HelloDll * Method: Display * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_HelloDll_Display (JNIEnv *env, jclass jthis, jstring data) { jboolean bCopy; const char* cData = env->GetStringUTFChars(data, &bCopy); std::cout << cData << std::endl; env->ReleaseStringUTFChars(data, cData); }
jni头文件位置
设置工程为动态库:
设置-fPIC标志:
编译,可以生成动态库libHello.so
设置把libHello.so自动复制到HelloDll中的bin目录下: