作者:左少华 博客:http://blog.csdn.net/shaohuazuo/article/details/42932813 转载请注明出处:http://blog.csdn.net/shaohuazuo
结构体的作用:它有点像我们char字符驱动的 file_ops结构体,它定义各种函数对在(jni.h头文件详解一)中定义的各种数据的操作函数集体.
jint (JNICALL *GetVersion)(JNIEnv *env)
--模块信息:该模块主要针对的JNI接口的版本信息操作函数.
通过Java对象的构造方法,把当前对象传递到C中.C获取到该对象之后,保存Java对象的引用,并获取相应的方法等.
获取该对象之后,C会调用获取JNI版本的函数.获取版本号,并调用Java层的getVersion()函数,将版本号显示出来.如图:
package com.octopus.test03;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
public class Act1 extends Activity implements OnClickListener {
private final int WC = LinearLayout.LayoutParams.WRAP_CONTENT;
private final int FP = LinearLayout.LayoutParams.FILL_PARENT;
private Button btn, btn3;
public static Act1 ref;
public TextView tv;
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
ref = this;
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn = new Button(this);
btn.setId(101);
btn.setText("run(Adder)");
btn.setBackgroundResource(R.drawable.ic_launcher);
btn.setOnClickListener(this);
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(120, 50);
param.topMargin = 10;
layout.addView(btn, param);
btn3 = new Button(this);
btn3.setId(103);
btn3.setText("exit");
btn3.setBackgroundResource(R.drawable.ic_launcher);
btn3.setOnClickListener(this);
layout.addView(btn3, param);
tv = new TextView(this);
tv.setTextColor(Color.WHITE);
tv.setText("");
LinearLayout.LayoutParams param2 = new LinearLayout.LayoutParams(FP, WC);
param2.topMargin = 10;
layout.addView(tv, param2);
setContentView(layout);
}
public void onClick(View v) {
if (v == btn) {
int a = 1, b = 1;
GetVersion adder = new GetVersion();
} else if (v == btn3) {
finish();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
package com.octopus.test03;
import java.lang.ref.WeakReference;
import android.os.Handler;
import android.os.Message;
public class GetVersion {
private static Handler h;
static {
System.loadLibrary("HelloNdk");
}
public GetVersion() {
h = new Handler() {
public void handleMessage(Message msg) {
Act1.ref.setTitle(msg.obj.toString());
}
};
nativeSetup(new WeakReference(this));
}
private static void getVersion(Object version_ref, int what,int message)
{
String obj1 = "Jni Version is : "+ message;
Message m = h.obtainMessage(what, obj1);
h.sendMessage(m);
}
private native void nativeSetup(Object weak_this);
}
1 /* DO NOT EDIT THIS FILE - it is machine generated */
2 #include "com_octopus_test03_GetVersion.h"
3 /* Header for class com_octopus_test03_GetVersion */
4
5 /*
6 * Class: com_octopus_test03_GetVersion
7 * Method: nativeSetup
8 * Signature: (Ljava/lang/Object;)V
9 */
10
11 jclass mClass;
12 jobject mObject;
13 jmethodID mid;
14
15 JNIEXPORT void JNICALL Java_com_octopus_test03_GetVersion_nativeSetup
16 (JNIEnv *env, jobject this, jobject weak_this)
17 {
18 jint version =0;
19 jclass class = (*env)->GetObjectClass(env,this);
20 mClass = (jclass)(*env)->NewGlobalRef(env,class);
21 mObject = (*env)->NewGlobalRef(env,weak_this);
22 mid = (*env)->GetStaticMethodID(env, mClass,"getVersion","(Ljava/lang/Object;II)V");
23
24 version = (*env)->GetVersion(env); //我们通过这个方法获取版本信息.并通过回调java的getVersion()方法显示版本号.
25 (*env)->CallStaticVoidMethod(env,mClass,mid,mObject,1,version);
26 return ;
27 }
SRC_PATH_ROOT:=$(LOCAL_PATH)/../../src
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := HelloNdk
LOCAL_SRC_FILES := com_octopus_test03_GetVersion.c
include $(BUILD_SHARED_LIBRARY)
.
转载请说明出处: http://blog.csdn.net/shaohuazuo/
.
(DefineClass,FindClass)
jclass (JNICALL *DefineClass) (JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len);
jclass (JNICALL *FindClass) (JNIEnv *env, const char *name);
--模块信息:这个模块主要是C或者C++中如何获取Java的Class类对象. 这个接口再Android上没有得到支持.
函数原型:jclass (JNICALL *DefineClass) (JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len);
描 述: 从二进制的.class的数据缓冲区中加载类.
参 数: env java本地接口指针.
name 需要加载类的简短名称.比如下载需要加载一个com/zuoshaohua/Test.java这个类,那么该名称就是 Test
loader 类加载器对象.该类用来加载java字节码.class文件
buf 这个是字节码缓冲区数组.
len 该数组的长度.
返回值:
返回一个jclass类型的结构体.他对应的是Java中的类相关信息.
例 程:
Java类加载器.也就是我们的loader参数的详细介绍.
在这里我们简单的说说loader的作用.在Java语言中loader是一个将 .class文件加载到内存的一个类加载器.
写一个测试的java类.他用来输出一个字符串..我们把他编译成一个.class文件.然后使用DefineClass进行加载.
并再Activity中输出该字符串.
package com.octopus.test03;
import java.lang.ref.WeakReference;
import android.os.Handler;
import android.os.Message;
public class DefindClassTest {
ClassLoader loader;
private static Handler h;
static {
System.loadLibrary("HelloNdk");
}
public DefindClassTest() {
h = new Handler() {
public void handleMessage(Message msg) {
Act1.ref.setTitle(msg.obj.toString());
}
};
loader = DefindClassTest.class.getClassLoader();
if(loader==null){
System.out.println("loader error\n");
}
//将获得的类加载器,传入到C层.
nativeSetup(new WeakReference(loader));
}
private static void getVersion(Object version_ref, Object test, int what,int message)
{
String obj1 = "Jni Version is : "+ message+ "C Create obj is"+ test;
Message m = h.obtainMessage(what, obj1);
h.sendMessage(m);
}
private native void nativeSetup(Object weak_this);
}
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "com_octopus_test03_DefindClassTest.h"
#include
#include
#include
#include
#include
#include
/*
* Class: com_octopus_test03_DefindClassTest
* Method: nativeSetup
* Signature: (Ljava/lang/Object;)V
*/
/*
jclass (JNICALL *DefineClass) (JNIEnv *env, const char *name, jobject loader, const jbyte *buf,jsize len);
*/
jclass mClass;
jobject mObject;
jmethodID mid;
JNIEXPORT void JNICALL Java_com_octopus_test03_DefindClassTest_nativeSetup
(JNIEnv *env, jobject this, jobject weak_this){
int fd;
off_t len;
jint ret;
int pos;
off_t tmplen;
jbyte *buf = NULL;
jclass testclass;
jint version =0;
jobject mOjbect1;
jobject obj1;
jclass class = (*env)->GetObjectClass(env,this);
mClass = (jclass)(*env)->NewGlobalRef(env,class);
//我们需要获取到DefineClassTest该类的类加载器.
mObject = (*env)->NewGlobalRef(env,weak_this);
//使用c读取我们需要加载的文件.
fd = open("/system/Test.class",O_RDONLY);
len = lseek(fd, 0, SEEK_END);
buf = calloc(len,1);
if(buf == NULL){
printf("calloc error \n");
return;
}
lseek(fd, 0,SEEK_SET);
pos = 0;
tmplen = len;
while(tmplen > 0){
ret += read(fd,buf+ret,tmplen-ret);
pos +=ret;
tmplen -=ret;
}
close(fd);
//使用DefineClass函数加载这个类
testclass = (*env)->DefineClass(env,"Test",mObject,buf,len);
if(testclass == NULL)
{
return;
}
free(buf);
obj1 = (*env)->AllocObject(env,testclass);
//生成一个对象,并调用该对象的方法.
mid = (*env)->GetStaticMethodID(env, mClass,"getVersion","(Ljava/lang/Object;Ljava/lang/Object;II)V");
version = (*env)->GetVersion(env);
(*env)->CallStaticVoidMethod(env,mClass,mid,this,obj1,1,version);
return ;
}
函数原型:jclass (JNICALL *FindClass) (JNIEnv *env, const char *name);
描 述: 该函数用于加载本地定义的类。它将搜索由CLASSPATH 环境变量为具有指定名称的类所指定的目录和 zip 文件。
该CLASSPATH一般为:
#set java environment
JAVA_HOME=/home/xxx/java/jdk1.6.0_12
export JRE_HOME=/home/xxx/java/jdk1.6.0_12/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
findClass函数的java背景知识在我的博客由介绍:
参 数: env java本地接口指针.
name 需要加载类的简短名称.比如下载需要加载一个com/zuoshaohua/Test.java这个类,该参数就是 "com/zuoshaohua/Test"
返回值:
返回一个jclass类型的结构体.他对应的是Java中的类相关信息.它是类的字节码对象.
例 程:
1.MainActivity的onCreate()方法中初始化一个ManPerson.
2.在ManPerson的构造函数最后我们会调用nativeSetup把ManPerson对象传递到C中.
3.我们会再C中得到ManPerson的属性Id信息,并保存起来.并使用findClass()方法获取Person类字节码对象,并生成Person对象的全集引用.
4.当我们点击应用层的btn时,C会获取ManPerson的信息.使用bean的setXxx()给Person对象赋值.并返回给对象到java层.
package com.zuoshaohua;
import com.zuoshaohua.ndk.ManPerson;
import com.zuoshaohua.ndk.NativeExec;
import com.zuoshaohua.ndk.Person;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener{
private Button runbtn;
private Button exitbtn;
private ManPerson manPerson;
private TextView personView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
exitbtn = (Button) this.findViewById(R.id.exit);
runbtn = (Button) this.findViewById(R.id.run);
personView = (TextView) this.findViewById(R.id.personView);
manPerson = new ManPerson("zuoshaohua",33,"男");
runbtn.setOnClickListener(MainActivity.this);
exitbtn.setOnClickListener(this);
}
@Override
public void onClick(View arg0) {
int id = arg0.getId();
switch (id) {
case R.id.run:
Person p = (Person)NativeExec.nativeExec(); //获取c代码生成对象.
personView.setText("name ="+ p.getName()+ "age="+p.getAge()+"gender="+p.getGender()); //输出这个对象的值.
break;
case R.id.exit:
this.finish();
break;
default:
this.finish();
break;
}
}
}
package com.zuoshaohua.ndk;
public class ManPerson {
private String name;
private int age;
private String gender;
static
{
System.loadLibrary("HelloNdk"); //加载动态库文件.
}
public ManPerson(String name, int age, String gender){
this.name = name;
this.age = age;
this.gender =gender;
nativeSetup();
}
private native void nativeSetup();
}
package com.zuoshaohua.ndk;
public class NativeExec {
public static native Object nativeExec();
}
package com.zuoshaohua.ndk;
public class Person {
private String name;
private int age;
private String gender;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
#include "com_zuoshaohua_ndk_ManPerson.h"
#include "com_zuoshaohua_ndk_NativeExec.h"
/*
* Class: com_zuoshaohua_ndk_ManPerson
* Method: nativeSetup
* Signature: ()V
*/
jobject m_obj, p_obj;
jfieldID name_id,age_id,gender_id;
jmethodID pname_mid,page_mid,pgender_mid;
JNIEXPORT void JNICALL Java_com_zuoshaohua_ndk_ManPerson_nativeSetup
(JNIEnv *env, jobject this)
{
#if 1
jclass clz = (*env)->GetObjectClass(env,this); //通过ManPerson的对象获取ManPerson字节码对象.
m_obj = (*env)->NewGlobalRef(env,this); //将这个对象设置为全局引用.
name_id = (*env)->GetFieldID(env,clz,"name","Ljava/lang/Object;"); //获取ManPerson对象的属性.
age_id = (*env)->GetFieldID(env,clz,"age","I");
gender_id = (*env)->GetFieldID(env,clz,"gender","Ljava/lang/Object;");
jclass personclz = (*env)->FindClass(env,"com/zuoshaohua/ndk/Person"); //通过FindClass方法获取Person类的字节码对象.
jmethodID constr =(*env)->GetMethodID(env,personclz,"", "()V"); //获取这个对象无参的构造函数.
jobject ref = (*env)->NewObject(env,personclz,constr); //生成Person对象.
p_obj = (*env)->NewGlobalRef(env, ref); //将Person对象设置为全局引用.
pname_mid = (*env)->GetMethodID(env,personclz,"setName","(Ljava/lang/Object;)V"); //获取Person的Setxxx()方法的ID.
page_mid = (*env)->GetMethodID(env,personclz,"setAge", "(I)V");
pgender_mid = (*env)->GetMethodID(env,personclz,"setGender","(Ljava/lang/Object;)V");
#endif
}
/*
* Class: com_zuoshaohua_ndk_NativeExec
* Method: nativeExec
* Signature: ()Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_com_zuoshaohua_ndk_NativeExec_nativeExec
(JNIEnv *env, jclass this)
{
#if 1
jint age = 0;
jstring name,gender;
name = (*env)->GetObjectField(env,m_obj,name_id); //获取ManPerson属性的值.
gender = (*env)->GetObjectField(env,m_obj,gender_id);
age = (*env)->GetIntField(env,m_obj,age_id);
(*env)->CallVoidMethod(env, p_obj,pname_mid,name); //调用Person的Setxxx()方法给Person对象赋值.
(*env)->CallVoidMethod(env, p_obj,page_mid,age);
(*env)->CallVoidMethod(env, p_obj,pgender_mid,gender);
//(*env)->SetIntField(env,p_obj,age_id,10); //返回Person对象.
return p_obj;
#endif
}
转载请注明出处: http://blog.csdn.net/shaohuazuo/article/details/42932813
jmethodID (JNICALL *FromReflectedMethod)(JNIEnv *env, jobject method);
jfieldID (JNICALL *FromReflectedField) (JNIEnv *env, jobject field);
jobject (JNICALL *ToReflectedMethod)(JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);
jobject (JNICALL *ToReflectedField) (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);
函数背景知识介绍: 请看博客(Java反射机制)
java.lang.reflect:
提供类和接口,以获得关于类和对象的反射信息。在安全限制内,
反射允许编程访问关于加载类的字段、方法和构造方法的信息,
并允许使用反射字段、方法和构造方法对其底层对等项进行操作。
更多相关知识可以参考http://www.javaweb.cc/help/JavaAPI1.6/
也可以进入博客:?????????????
函数原型: jmethodID (JNICALL *FromReflectedMethod)(JNIEnv *env, jobject method);
描 述: 通过java.lang.reflect中Method类的对象获取一个函数的MethodID. 就可以调用Java中某个方法.
参 数: env java native interface porint,(java本地接口指针)
method 这个是jva.lang.reflect.Method对象.
要获取Method对象第一步.需要获取Class对象.再通过Class对象获取Method.
1.获取Class对象的三种方法是:
1.2) 对象.getClass(),例如,Class pclass = new Person().getClass()
1.3) Class.forName(“类名”),例如,Class pclass = Class.forName(“com.zuoshaohua.Person”);
2.获取Method对象,详细方法介绍可以参考http://www.javaweb.cc/help/JavaAPI1.6/手册
2.1)Class.getMethods(),
2.2)Class.getMethod(String, Class[]),
2.3)Class.getDeclaredMethods(),
2.4)Class.getDeclaredMethod(String, Class[])
1.5) ToReflectedMethod()通过C中的JNI标准获取Methdod对象. 返回值:返回一个方法的MethodID指针.
函数原型: jfieldID (JNICALL *FromReflectedField) (JNIEnv *env, jobject field);
描 述:通过java.lang.reflect中Field类的对象获取字段对象.可以获取这个字段的jfieldID了.
参 数: env java native interface porint,(java本地接口指针)
field Field对象,这个对象主要用来描述java中的字段信息.通过这个类对象.我们可以获得
这个字段的名称,类型等等信息.
1.获取这个对象由如下5种方法:
1.1)Class.getDeclaredField(String name);
返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
1.2)Class.getDeclaredFields();
返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
1.3)Class.getField(String name);
返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
1.4)Class.getField();
返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
1.6)ToReflectedFile()
通过C中JNI标准中提供的上面的函数,也可以获取Field对象.
返回值:返回一个字段的jfieldID指针.
函数原型: jobject (JNICALL *ToReflectedMethod)(JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);
描 述: 这个方法是通过方法的methodId返回一个java.lang.reflect.Method对象,是FromReflectedMethod的反操作.
参 数: env java native interface porint,(java本地接口指针)
cls 该方法的类对象.可以通过FindClass()获取.如果知道对象的话可以使用GetObjectClass()来获取这个jclass对象.
methodID 这个对象是jmethodID指针.可以通过GetMethodID方法获取.
isStatic 该方法是不是静态的,JNI标准中提供了两个宏表示.JNI_FALSE,和JNI_TRUE.
返回值:返回一个Method对象.也就是说再FromReflectedMethod 中多了一种方法可以获取Method对象的方法.
函数原型: jobject (JNICALL *ToReflectedField) (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);
描 述: 通过filedID可以返回一个java.lang.reflect.Field对象.
参 数: env java native interface porint,(java本地接口指针)
cls 该方法的类对象.可以通过FindClass()获取.如果知道对象的话可以使用GetObjectClass()来获取这个jclass对象.
methodID 这个对象是jField指针.可以通过GetFieldID方法获取.
isStatic 该方法是不是静态的,JNI标准中提供了两个宏表示.JNI_FALSE,和JNI_TRUE.
返回值: 返回一个Field对象.
1. 定义一个Person类.这个Person类三个属性.name, age, gender.还有getxxx()和setxxx()方法.
2. 定义一个Android的界面.它的MainActivity类关联了一个Person对象.也就是,Person类是Activity的一个属性.
3. 在MainActivity中,静态初始化这个Person对象.我们使用该静态对象.p.getClass()获取类Class对象clz.
4. 我们需要获取这个Class中的Method对象和Field对象.clz.getMethod(); clz.getField对象.
通过 ReflectMethodDeom本地方法和ReflectFieldDemo本地方法传入到C层.
5. c通过这两个对象获取到对象的jfieldID对象和jmethodID.并进行相应的操作.
1. MainActivity代码
package com.zuoshaohua.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener {
private static Person p = new Person("zuoshaohua",33,"男");
private Button runBtn;
private Button exitBtn;
TextView textView;
static {
System.loadLibrary("reflect");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
runBtn = (Button)this.findViewById(R.id.run);
exitBtn = (Button)this.findViewById(R.id.exit);
textView = (TextView)this.findViewById(R.id.personView);
this.runBtn.setOnClickListener(this);
this.exitBtn.setOnClickListener(this);
}
private void refelectTest(){
Class extends Person> c = p.getClass();
try {
StringBuffer sb = new StringBuffer();
Method method = c.getMethod("setAge", int.class);
//Field field = c.getField("age");
Field field = c.getDeclaredField("age");
sb.append("oldName ="+p.getName()+"oldAge="+p.getAge()+ "oldGender="+p.getGender()+"\n");
Field field1 = ReflectFieldDemo(p,field); //调用本地方法.将描述age字段的Field对象传进去.
//field1.set(p, "shaohuazuo");
Method m1 = ReflectMethodDemo(p,method); //调用本地方法.将描述setAge()方法的Method对象传入到C层代码.
sb.append("oldName1 ="+p.getName()+"oldAge1="+p.getAge()+ "oldGender1="+p.getGender()+"\n");
Object args[] = new Object[1];
args[0] = new String("shaohuazuo");
m1.invoke(p, args); //调用返回的方法.
field1.setAccessible(true);
String name =(String)field1.get(p);
sb.append("newName ="+name+"newAge="+p.getAge()+"newGender="+p.getGender());
textView.setText(sb.toString());
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private static native Field ReflectFieldDemo(Person p,Field f);
private static native Method ReflectMethodDemo(Person p, Method m);
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
switch(arg0.getId())
{
case R.id.run:
refelectTest();
break;
case R.id.exit:
this.finish();
break;
default:
this.finish();
break;
}
}
}
2. Person.java代码
package com.zuoshaohua.reflect;
public class Person {
private String name;
private int age;
private String gender;
public Person(String string, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
3. 生成.h头文件.
zshh@HP:~/work/android/jni/Reflect/jni$
javah -o reflect.h -classpath ../bin/classes com.zuoshaohua.reflect.MainActivity
4. reflect.h代码
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_zuoshaohua_reflect_MainActivity */
#ifndef _Included_com_zuoshaohua_reflect_MainActivity
#define _Included_com_zuoshaohua_reflect_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_zuoshaohua_reflect_MainActivity
* Method: ReflectFieldDemo
* Signature: (Lcom/zuoshaohua/reflect/Person;Ljava/lang/reflect/Field;)Ljava/lang/reflect/Field;
*/
JNIEXPORT jobject JNICALL Java_com_zuoshaohua_reflect_MainActivity_ReflectFieldDemo
(JNIEnv *, jclass, jobject, jobject);
/*
* Class: com_zuoshaohua_reflect_MainActivity
* Method: ReflectMethodDemo
* Signature: (Lcom/zuoshaohua/reflect/Person;Ljava/lang/reflect/Method;)Ljava/lang/reflect/Method;
*/
JNIEXPORT jobject JNICALL Java_com_zuoshaohua_reflect_MainActivity_ReflectMethodDemo
(JNIEnv *, jclass, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif
5. reflect.c代码
#include "reflect.h"
#include
#include
#if 0
jmethodID (JNICALL *FromReflectedMethod) (JNIEnv *env, jobject method);
jfieldID (JNICALL *FromReflectedField) (JNIEnv *env, jobject field);
jobject (JNICALL *ToReflectedMethod) (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);
jobject (JNICALL *ToReflectedField) (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);
#endif
jclass clazz;
/*
* Class: com_zuoshaohua_reflect_MainActivity
* Method: ReflectFieldDemo
* Signature: (Lcom/zuoshaohua/reflect/Person;Ljava/lang/reflect/Field;)Ljava/lang/reflect/Field;
*/
JNIEXPORT jobject JNICALL Java_com_zuoshaohua_reflect_MainActivity_ReflectFieldDemo
(JNIEnv * env, jclass this, jobject pthis, jobject fthis)
{
jint age =0;
jclass clz =(*env)->GetObjectClass(env,pthis); //通过Person对象获取他的Class对象信息,从而得到一个jclass对象.
jfieldID age_id = (*env)->FromReflectedField(env,fthis); //通过Field对象获取Person属性的jfieldID指针.
age = (*env)->GetIntField(env,pthis,age_id); //通过这个对象和age_id获取这个属性的值.
__android_log_print(ANDROID_LOG_INFO, "ReFlectFieldDemo", "age: %d", age);
jfieldID name_id = (*env)->GetFieldID(env,clz,"name","Ljava/lang/String;"); //获取name字段的jfieldID.
__android_log_print(ANDROID_LOG_INFO, "ReFlectFieldDemo", "end!!!!!");
return (*env)->ToReflectedField(env,clz,name_id,JNI_FALSE); //通过jfieldID生成一个Java的Field对象.并返回.
}
/*
* Class: com_zuoshaohua_reflect_MainActivity
* Method: ReflectMethodDemo
* Signature: (Lcom/zuoshaohua/reflect/Person;Ljava/lang/reflect/Method;)Ljava/lang/reflect/Method;
*/
JNIEXPORT jobject JNICALL Java_com_zuoshaohua_reflect_MainActivity_ReflectMethodDemo
(JNIEnv *env , jclass this, jobject pthis, jobject mthis)
{
//我们使用mthis.来获取jmethodID指针.并通过该指针调用到set方法.来改变Person属性的值.
jclass pclazz = (*env)->GetObjectClass(env,pthis);
jmethodID setAgeId = (*env)->FromReflectedMethod(env,mthis);
(*env) ->CallVoidMethod(env,pthis,setAgeId,100);
__android_log_print(ANDROID_LOG_INFO,"ReflectMethodDemo","is callVoidMethod Done!!!!\n");
jmethodID setName_id = (*env)->GetMethodID(env,pclazz,"setName","(Ljava/lang/String;)V");
return (*env)->ToReflectedMethod(env, pclazz,setName_id, JNI_FALSE);
}
6. Android.mk代码
SRC_PATH_ROOT:=$(LOCAL_PATH)/../../src
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := reflect
LOCAL_SRC_FILES := reflect.c
LOCAL_LDLIBS := -llog
#LOCAL_SHARED_LIBRARIES :=libc
include $(BUILD_SHARED_LIBRARY)
作者:左少华 博客:http://blog.csdn.net/shaohuazuo/article/details/42932813 转载请注明出处:http://blog.csdn.net/shaohuazuo