**1,c/c++ 调用java中的实例属性
**
看下MainActivity的代码
package com.example.acer.test_18_02_21;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
int anInt=10;
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
Log.i("zhang_xin",anInt+"值值值值值");
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
}
native-lib
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT jstring
JNICALL
Java_com_example_acer_test_118_102_121_MainActivity_stringFromJNI(
JNIEnv *env,
jobject jobj) {
//通过对象实例来获取jclass,相当于java中的getClass方法
jclass cls = env->GetObjectClass(jobj);
//获取类中某个非静态成员变量的ID(域ID)
//anInt:MainActivity中的属性名称
//I:属性签名,int值的签名是一个大写的I
jfieldID jintid = env->GetFieldID(cls, "anInt", "I");
//第一个参数:某个 Java 对象实例
//field就是英文属性、成员变量
//此时a的值就是MainActivity中定义的anInt的值,即10;
jint a=env->GetIntField(jobj, jintid);
a=25;
//修改MainActivity中anInt的值
env->SetIntField(jobj,jintid,a);
std::string hello = "Hello 我乃西凉马超是也from C++";
return env->NewStringUTF(hello.c_str());
}
MainActivity显示修改后的anInt值是25
总结下步骤:
1)先获取当前类
2)再获取属性ID
3)env环境指针调用相关方法,需要参数,get和set函数(方法)
**
2,c/c++调用java中的静态属性
**
MainActivity代码
package com.example.acer.test_18_02_21;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
static int s_anInt=11;
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("zhang_xin",s_anInt+"前");
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
Log.i("zhang_xin",s_anInt+"后");
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
}
native-lib代码
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT jstring
JNICALL
Java_com_example_acer_test_118_102_121_MainActivity_stringFromJNI(
JNIEnv *env,
jobject jobj) {
//静态用到cls替代
jclass cls=env->GetObjectClass(jobj);
jfieldID js_intid=env->GetStaticFieldID(cls,"s_anInt","I");
//得到MainActivity中s_anInt的值,为11
jint a= env->GetStaticIntField(cls,js_intid);
env->SetStaticIntField(cls, js_intid,60);
std::string hello = "Hello 我乃西凉马超是也from C++";
return env->NewStringUTF(hello.c_str());
}
看下打印输出结果
02-22 18:38:07.358 25368-25368/? I/zhang_xin: 11前
02-22 18:38:07.358 25368-25368/? I/zhang_xin: 60后
总结下步骤:
- 先获取当前类
2)在获取属性ID
3)env调用相关方法,和普通的变量区别是参数不同
**
3.c/c++调用java类的实例方法
**
看下MainActivity类的代码
package com.example.acer.test_18_02_21;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
public int temp(int a){
Log.i("zhang_xin",a+"C++中调用");
return a;
}
}
native-lib中的代码
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT jstring
JNICALL
Java_com_example_acer_test_118_102_121_MainActivity_stringFromJNI(
JNIEnv *env,
jobject jobj) {
jclass cls = env->GetObjectClass(jobj);
//cls:来自哪个class
//方法的名称
//方法的签名:括号里面的I是参数类型,后面的I是返回值类型
jmethodID jmid=env->GetMethodID(cls,"temp","(I)I");
//第一个参数,Java对象实例
//第二个参数,methodID:指定方法的ID
//第三个参数 args:输入参数列表
//调用方法使用Call**;
//jobj 此处代表MainActivityl.class;
//三个点代表可变参数,MainActivity方法中的参数
env->CallIntMethod(jobj, jmid,56);
std::string hello = "Hello 我乃张飞是也from C++";
return env->NewStringUTF(hello.c_str());
}
看下MainActivity的输出
56C++中调用
在这里有一点要注意,CallIntMethod在执行中会转化为CallIntMethodv,当参数不明确的时候需要调用CallIntMethodA;
步骤
1)先获取当前类
2)再获取属性ID
3)env call系列
jclass cls = env->GetObjectClass(jobj);
jmethodID jmid = env->GetMethodID(cls,“temp”,"(I)I");
env->CallIntMethod(jobj, jmid,56);
**
4,C/C++调用java静态方法
**
看下MainActivity
package com.example.acer.test_18_02_21;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
public static int stemp(int a,String str){
Log.i("zhang_xin",a+" C++中调用 "+str);
return a;
}
}
native-lib
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT jstring
JNICALL
Java_com_example_acer_test_118_102_121_MainActivity_stringFromJNI(
JNIEnv *env,
jobject jobj) {
jclass cls = env->GetObjectClass(jobj);
//String类型是一个类类型,大写的L+类的全名,所以是Ljava/lang/String;
jmethodID jsmid = env->GetStaticMethodID(cls,"stemp","(ILjava/lang/String;)I");
jstring str=env->NewStringUTF("zhang_xin");
env->CallStaticIntMethod(cls, jsmid,41,str);
std::string hello = "Hello 我乃关羽是也from C++";
return env->NewStringUTF(hello.c_str());
}
看下打印输出的结果
I/zhang_xin: 41 C++中调用 zhang_xin
**
5,c/c++调用其他子类的方法
**
我们创建一个父类和一个子类
package com.example.acer.test_18_02_21;
/**
* Created by acer on 2018/2/22.
*/
public class Father {
public Father(){
}
public void drive(){
System.out.println("我会开车");
}
}
package com.example.acer.test_18_02_21;
/**
* Created by acer on 2018/2/22.
*/
public class Son extends Father {
public Son(){
}
@Override
public void drive() {
System.out.println("我正在学开车");
}
}
看下MainActivity类
package com.example.acer.test_18_02_21;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
Father son1=new Son();
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
}
看下native-lib
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT jstring
JNICALL
Java_com_example_acer_test_118_102_121_MainActivity_stringFromJNI(
JNIEnv *env,
jobject jobj) {
jclass cls = env->GetObjectClass(jobj);
jfieldID jsid=env->GetFieldID(cls,"son1","Lcom/example/acer/test_18_02_21/Father;");
//Son类是一个Object
jobject son1=env->GetObjectField(jobj, jsid);
//通过当前对象找到该类
jclass cls_son=env->GetObjectClass(son1);
//注意这里的class是Son类的Class;方法名drive
jmethodID jomid = env->GetMethodID(cls_son, "drive", "()V");
//注意jobj是MainActivity的,这里不能用,我们要用son1
//没有参数传空
env->CallVoidMethod(son1, jomid, NULL);
std::string hello = "Hello 我乃关羽是也from C++";
return env->NewStringUTF(hello.c_str());
}
看下输出结果
System.out: 我正在学开车
步骤:先获取子类对象,然后访问子类的方法
**
6,c/c++通过子类对象调用父类方法
**
其他的三个类与5一样;我们只需改下native-lib的方法
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT jstring
JNICALL
Java_com_example_acer_test_118_102_121_MainActivity_stringFromJNI(
JNIEnv *env,
jobject jobj) {
jclass cls = env->GetObjectClass(jobj);
jfieldID jsid=env->GetFieldID(cls,"son1","Lcom/example/acer/test_18_02_21/Father;");
jobject son1=env->GetObjectField(jobj, jsid);
jclass cls_son=env->GetObjectClass(son1);
//父类的class
jclass jfcls = env->GetSuperclass(cls_son);
//方法的ID
jmethodID jfomid = env->GetMethodID(jfcls,"drive","()V");
//这里要传两个对象,一个是子类对象,一个是父类对象
env->CallNonvirtualVoidMethod(son1, jfcls, jfomid, NULL);
std::string hello = "Hello 我乃张飞是也from C++";
return env->NewStringUTF(hello.c_str());
}
看下运行结果
我会开车
7,获取某个类方法签名的窍门
首先找到该类,以Father类为例;
其次,在Terminal中,进入该类的目录
最后输入 javap -s -p Father
获取类的方法签名