DNK编程 JNI 之 javah

本文内容为原创,转载者请注明原始作者为seker,原始出处http://blog.csdn.net/seker_xinjian/archive/2011/04/14/6323835.aspx. 以避免版权纠纷!

 

  在进行Android NDK编程中,我们不可避免的要使用到JNI。JNI本质来讲是native代码(C++),它是托管程序集(Java语言编写的)与非托管程序集(C++语言编写的)的桥梁。要做到桥梁的作用,JNI就必须要求Java语言的代码和C++语言的代码在定义上要相互符合,否则上层应用调用底层实现的时候就找不到底层了。

  例如,Java层定义了这样一个类:<root>/jni/Test1.java

public class Test1 { private static final float PI = 3.1415926f; private native void function1(int a); private native String function2(); } 

  那么它的两个native函数所对应的native的定义必须如下:

#undef Test1_PI #define Test1_PI 3.1415925f /* * Class: Test1 * Method: function1 * Signature: (I)V */ JNIEXPORT void JNICALL Java_Test1_function1(JNIEnv *, jobject, jint); /* * Class: Test1 * Method: function2 * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_Test1_function2(JNIEnv *, jobject); 

 

        请注意它的C++层的函数定义的函数名、参数以及返回值的规范,不符合规范的函数定义,在java层调用就会出错了。如果初学者想要手动的写这种JNI函数的定义的话,确实应该非常的小心谨慎才行。

 

        然而,JDK开发包中有一个小工具:javah,我们可以使用这个工具来自动生成Java层类对应的native层的函数定义。针对上面多提到的代码:<root>/jni/Test1.java,可以使用下面的命令行来操作:

        >> cd <root>/jni/

        >> javac Test1.java

        >> javah Test1

这样就能生成一个Test1.h文件,打开该文件,我们就可以看到生成好的C++语言的函数定义。

        虽然如此,我们在实际开发中还是会遇到一个问题:那就是Java包名对javah的要求。例如,我们定义一个类<root>/jni/com/test/Test2.java
package com.test; public class Test2 { private static final float PI = 3.1415926f; private native void function3(int a); private native String function4(); } 
        如果我们依然使用上面的命令行,就无法生成相应的.h文件了。正确的方法如下:
        >> cd <root>/jni/com/test/
        >> javac Test2.java
        >> javah -classpath <root>/jni/ com.test.Test2
        或者
        >> cd <root>/jni/
        >> javac com/test/Test2.java
        >> javah com.test.Test2
        可见,如果Java类声明了包名,在使用javah的时候需要指明-classpath参数(默认为当前目录)
        最终的头文件是com_test_Test2.h,我们还可以给javah传入 -o 参数,指定输出路径和目标文件名,如:
        javah -o <root>/jni/com/Test2.h com.test.Test2
        头文件的内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_test_Test2 */ #ifndef _Included_com_test_Test2 #define _Included_com_test_Test2 #ifdef __cplusplus extern "C" { #endif #undef com_test_Test2_PI #define com_test_Test2_PI 3.1415925f /* * Class: com_test_Test2 * Method: function3 * Signature: (I)V */ JNIEXPORT void JNICALL Java_com_test_Test2_function3 (JNIEnv *, jobject, jint); /* * Class: com_test_Test2 * Method: function4 * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_test_Test2_function4 (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif 

 

你可能感兴趣的:(java,编程,function,jni,Class,语言)