jni应用(构造和方法)

来源:互联网 发布:02年韩国黑哨 知乎 编辑:程序博客网 时间:2024/06/09 13:59

概述

   jni 是java native interface简称,是Java在C或C++的实现接口,共存在Java的类中。所以在jni里注册的是Java的类。不过以“/”代替Java的“.”.


JNI_OnLoad 方法

   /*************native jniTestClass.cpp******************************/

   #include "jni.h"
   #include "JNIHelp.h"

static const char *classPathName ="android/com/test/testClass";

static JNINativeMethod methods[ ] = {
    { "nativeTest", "(ILandroid/os/Parcel;Ljava/lang/Object;)I", (void *)android_com_test_testClass_nativeTest },
};

/*
 * Register several Native methods for one class.
 */
static int registerNativeMethods(JNIEnv *env, const char *className,
                                 JNINativeMethod *gMethods, int numMethods)
{
    jclass clazz;

    clazz = env->FindClass(className);
    if (clazz == NULL) {
    ALOGE("Native registration unable to find class '%s'", className);
    return JNI_FALSE;
    }
    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
    ALOGE("RegisterNatives failed for '%s'", className);
    return JNI_FALSE;
    }

    return JNI_TRUE;
}

/*
 * Register Native methods for all classes we know about.
 *
 * returns JNI_TRUE on success.
 */
static int registerNatives(JNIEnv *env)
{
    if (!registerNativeMethods(env, classPathName,
                               methods, sizeof(methods) / sizeof(methods[0]))) {
    return JNI_FALSE;
    }

    return JNI_TRUE;
}

// ----------------------------------------------------------------------------

/*
 * This is called by the VM when the shared library is first loaded.
 */

typedef union
{
    JNIEnv *env;
    void *venv;
} UnionJNIEnvToVoid;

jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
    UnionJNIEnvToVoid uenv;
    uenv.venv = NULL;
    jint result = -1;
    JNIEnv *env = NULL;

    ALOGI("JNI_OnLoad");

    if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
    ALOGE("ERROR: GetEnv failed");
    goto bail;
    }
    env = uenv.env;

    if (registerNatives(env) != JNI_TRUE) {
    ALOGE("ERROR: registerNatives failed");
    goto bail;
    }

    result = JNI_VERSION_1_4;

bail:
    return result;
}


Jni Java 对应方法

  /*************javaTestClass.java******************************/

  packageandroid.com.test;

  import android.util.Log;
  import android.os.Parcel;
  import android.os.Parcelable;

public classTestClass{

  private
    final static String TAG = "TestClass";

private
    int mNativeContext; // native context

public
    native final int nativeTest(int dataType, Parcel objParcel, Object objDvbEit);/*******与 jniTestClass.cppmethods 对应*********/

static
    {
        // the name supplied to loadLibrary.
        Log.i(TAG, "load testjni lib");
        System.loadLibrary("testjni");   /*****调用JNI_OnLoad的方法******/
    }

public TestClass()

{

  nativeTest(0,null,null);/*****调用android_com_test_testClass_nativeTest******/

}

}


JNINativeMethod 类型定义

Java 和 C 函数的映射表数组,并在其中描述了函数的参数和返回值。这个数组的类型是JNINativeMethod,定义如下:

typedef struct {
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;

第一个变量name是Java中函数的名字。

第二个变量signature,用字符串是描述了函数的参数和返回值

第三个变量fnPtr是函数指针,指向C函数。

其中比较难以理解的是第二个参数,例如

"()V"

"(II)V"

"(Ljava/lang/String;Ljava/lang/String;)V"

 

实际上这些字符是与函数的参数类型一一对应的。

"()" 中的字符表示参数,后面的则代表返回值。例如"()V" 就表示void Func();

"(II)V" 表示 void Func(int, int);

 

具体的每一个字符的对应关系如下

字符 Java类型 C类型

V      void            void
Z       jboolean     boolean
I        jint              int
J       jlong            long
D      jdouble       double
F      jfloat            float
B      jbyte            byte
C      jchar           char
S      jshort          short

 

数组则以"["开始,用两个字符表示

[I       jintArray      int[]
[F     jfloatArray    float[]
[B     jbyteArray    byte[]
[C    jcharArray    char[]
[S    jshortArray   short[]
[D    jdoubleArray double[]
[J     jlongArray     long[]
[Z    jbooleanArray boolean[]

 

上面的都是基本类型。如果Java函数的参数是class,则以"L"开头,以";"结尾中间是用"/" 隔开的包及类名。而其对应的C函数名的参数则为jobject. 一个例外是String类,其对应的类为jstring

Ljava/lang/String; String jstring
Ljava/net/Socket; Socket jobject

如果JAVA函数位于一个嵌入类,则用$作为类名间的分隔符。

例如 "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z"





0 0