首页 > 代码库 > JNI——结构体(即java中的类)的传入与设置——NativeMethod映射表

JNI——结构体(即java中的类)的传入与设置——NativeMethod映射表

参考:http://www.cnblogs.com/skywang12345/archive/2013/05/26/3093593.html

java 类:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.skywang.ndk;
 
public class MyInfo {
    private String  mName;                    
    private int     mAge;
    private float   mHeight;
     
    public String toString(){
        return "mName:"+mName+", mAge:"+mAge+", mHeight:"+mHeight;
    }
}
============================================
Person.java:
  
package com.skywang.ndk;
 
public class Person {
     
    private String  mName;                    
    private int     mAge;
    private float   mHeight;
     
    public String toString(){
        return "mName:"+mName+", mAge:"+mAge+", mHeight:"+mHeight;
    }
 
}

  

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.skywang.ndk;
 
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
 
public class NdkParam extends Activity {
    public static final String TAG="skywang--NdkParam";
    public static final String TAG_MY="MY_skywang--NdkParam";
    /** Called when the activity is first created. */
    private Person person=null;
    private MyInfo myinfo = null;
     
     
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
         
        Log.d(TAG, "on create.");
        person = new Person();
        for (int i=0; i<3; i++) {
            getPersonInfoByIndex(person, i);
            Log.d(TAG, "person["+i+"] -- "+person);
        }
         
        Log.d(TAG, "==============================》MyInfo.《==================================");
        myinfo = new MyInfo();
        for (int i=0; i<3; i++) {
             
            getMyInfoByIndex(myinfo, i);
            Log.d(TAG, "myinfo["+i+"] -- "+myinfo);
        }
    }
     
    // jni
    private native int getPersonInfoByIndex(Person person, int index);
    private native int getMyInfoByIndex(MyInfo myinfo, int index);
 
    static {
        //System.loadLibrary("ndk_param");
        System.loadLibrary("ndk_param");
    }
}

  JNI:

+ View Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
头文件:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <jni.h>
#include <assert.h>
 
 
// 获取数组的大小
# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
// 指定要注册的类,对应完整的java类名
#define JNIREG_CLASS "com/skywang/ndk/NdkParam"
#define JNIPAR_CLASS "com/skywang/ndk/Person"
 
#define JNIPAR_CLASS_MYINFO "com/skywang/ndk/MyInfo"
 
// 引入log头文件
#include <android/log.h> 
 
// log标签
#define  TAG    "hello_param"
// 定义info信息
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)
// 定义debug信息
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
// 定义error信息
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)
 
// jfieldID结构体,用于保存类“Person.java”的filedID
struct PersonOffsets
{
    jfieldID    name;
    jfieldID    age;
    jfieldID    height;
} gPersonOffsets;
struct MyInfoOffsets
{
    jfieldID    name;
    jfieldID    age;
    jfieldID    height;
} gMyInfoOffsets;
 
// 与“Person.java”对应的结构体,用于保存数据,并将数据赋值给Person.java的成员
typedef struct tagPerson
{
    char    mName[10];
    int     mAge;
    float   mHeight;
}Person;
typedef struct tagMyInfo
{
    char    mName[10];
    int     mAge;
    float   mHeight;
}MyInfo;
 
// 定义了3个Person
static Person gPersons[] = {
    {"skywang", 25, 175},
    {"eman"   , 30, 166},
    {"Dan"    , 51, 172},
};
static MyInfo gMyInfos[] = {
    {"liu", 25, 175},
    {"gang"   , 30, 166},
    {"hong"    , 51, 172},
};
 
#define GPERSON_NUM NELEM(gPersons)
#define GMYINFO_NUM NELEM(gMyInfos)

  

+ View Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
c文件:
 
 
#include "ndk_param.h"
 
 
/*
 * 根据index获取Person信息。
 * 参数说明:
 *      env : JNI 接口指针。
 *      claszz : Java 类对象。
 *      person : 输入参数,java对象
 *      index : 输入参数,序列号。
 */
JNIEXPORT jint JNICALL
getPersonInfoByIndex(JNIEnv *env, jobject clazz, jobject person, jint index)
{
 
    // 若index无效,则直接返回-1。
    if ((int)index<0 || (int)index>=GPERSON_NUM)
        return -1;
 
    // 将Person数组(gPersons)中的第index个成员赋值给pPerson指针
    Person *pPerson = &gPersons[index];
         
    // 设置java对象person的mName
    jstring name = (*env)->NewStringUTF(env, pPerson->mName);
    (*env)->SetObjectField(env, person, gPersonOffsets.name, name);
    // 设置java对象person的mAge
    (*env)->SetIntField(env, person, gPersonOffsets.age, pPerson->mAge);
    // 设置java对象person的mHeight
    (*env)->SetFloatField(env, person, gPersonOffsets.height, pPerson->mHeight);
 
    LOGD("%s index-%d  mName:%s, mAge:%d, mHeight:%f\n",
            __func__, index, pPerson->mName, pPerson->mAge, pPerson->mHeight);
 
    return 0;
}
JNIEXPORT jint JNICALL getMyInfoByIndex(JNIEnv *env, jobject clazz, jobject myinfo, jint index)
{
    // 若index无效,则直接返回-1。
    if ((int)index<0 || (int)index>=GMYINFO_NUM)
        return -1;
     
    // 将Person数组(gPersons)中的第index个成员赋值给pPerson指针
    MyInfo *pMyInfo = &gMyInfos[index];
     
    // 设置java对象person的mName
    jstring name = (*env)->NewStringUTF(env, pMyInfo->mName);
    (*env)->SetObjectField(env, myinfo, gMyInfoOffsets.name, name);
     
    // 设置java对象person的mAge
    (*env)->SetIntField(env, myinfo, gMyInfoOffsets.age, pMyInfo->mAge);
    // 设置java对象person的mHeight
    (*env)->SetFloatField(env, myinfo, gMyInfoOffsets.height, pMyInfo->mHeight);
 
    LOGD("%s index-%d  mName:%s, mAge:%d, mHeight:%f\n",
            __func__, index, pMyInfo->mName, pMyInfo->mAge, pMyInfo->mHeight);
 
    return 0;
}
 
// 初始化函数,用于获取Java中各个成员对应的fieldID。
static void nativeClassInit (JNIEnv *env)
{  
    jclass personClass = (*env)->FindClass(env, JNIPAR_CLASS);
    jclass myinfoClass = (*env)->FindClass(env, JNIPAR_CLASS_MYINFO);
     
    // 获取Person的mName成员对应的FieldID,并保存到gPersonOffsets中
    gPersonOffsets.name     = (*env)->GetFieldID(env, personClass, "mName"  , "Ljava/lang/String;");
    gMyInfoOffsets.name     = (*env)->GetFieldID(env, myinfoClass, "mName"  , "Ljava/lang/String;");
         
    // 获取Person的mAge成员对应的FieldID,并保存到gPersonOffsets中
    gPersonOffsets.age      = (*env)->GetFieldID(env, personClass, "mAge"   , "I");
    gMyInfoOffsets.age      = (*env)->GetFieldID(env, myinfoClass, "mAge"   , "I");
         
    // 获取Person的mHeight成员对应的FieldID,并保存到gPersonOffsets中
    gPersonOffsets.height   = (*env)->GetFieldID(env, personClass, "mHeight", "F");
    gMyInfoOffsets.height   = (*env)->GetFieldID(env, myinfoClass, "mHeight", "F");
 
}
 
// Java和JNI函数的绑定表
static JNINativeMethod method_table[] = {
    { "getPersonInfoByIndex", "(Lcom/skywang/ndk/Person;I)I", (void*)getPersonInfoByIndex },//绑定
    { "getMyInfoByIndex", "(Lcom/skywang/ndk/MyInfo;I)I", (void*)getMyInfoByIndex },//绑定
     
};
 
// 注册native方法到java中
static int registerNativeMethods(JNIEnv* env, const char* className,
        JNINativeMethod* gMethods, int numMethods)
{
    jclass clazz;
    clazz = (*env)->FindClass(env, className);
    if (clazz == NULL) {
        return JNI_FALSE;
    }
    if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
        return JNI_FALSE;
    }
 
    return JNI_TRUE;
}
 
int register_ndk_param(JNIEnv *env)
{
    nativeClassInit(env);
    // 调用注册方法
    return registerNativeMethods(env, JNIREG_CLASS,
            method_table, NELEM(method_table));
}
 
// JNI_OnLoad在jni注册时,会被回调执行。
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv* env = NULL;
    jint result = -1;
 
    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        return result;
    }  
 
    register_ndk_param(env);
 
    // 返回jni的版本
    return JNI_VERSION_1_4;
}