java 调用c/c++ 的方法,很简单。我们勾选创建支持C/C++ 项目的时候,就已经生成了一个Demo
下面主要介绍,C/C++ 调用 java 的方法。
一、访问 java 成员非静态成员变量:
JNI 调用java非静态变量的 方法名格式 : Get<Type>Field() 例如 :int 类型参数 GetIntField()
JNI 调用java 静态变量的 方法名格式 : GetStatic<Type>Field() 例如 :int 类型参数 GetStaticIntField()
代码目录:
NdkUtils 类中的 java native 方法
public class NdkUtils {
// 非静态变量
public String name = "小明";
static {
System.loadLibrary("native-lib");
}
public native String getAccessFiled();
}
cpp目录下的 native-lib.cpp
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT jstring JNICALL Java_com_example_cf8_1012_ndk_NdkUtils_getAccessFiled(JNIEnv *env, jobject jobj) {
// 获取jclass 对象,后面要用
jclass clazz = env->GetObjectClass(jobj);
// 获取成员变量的jfieldID 参数说明:jclass ,变量名称 , 属性sig 签名
jfieldID fieldId = env->GetFieldID(clazz, "name", "Ljava/lang/String;");
// 根据 jfieldID 获取 该变量的值
jstring jstring1 = (jstring) env->GetObjectField(jobj, fieldId);
return jstring1;
}
MainActivity.class 中调用:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv1 = (TextView) findViewById(R.id.sample_text1);
tv1.setText(new NdkUtils().getAccessFiled());
}
}
运行结果:
详解:
jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)
获取非静态成员变量/方法的方法。
jclass clazz:所属的类的对象
const char* name :要获取变量的名称
const char* sig 所属类型的签名
静态成员变量/方法 对应的方法 : GetStaticFieldID(jclass clazz, const char* name, const char* sig)
下面附上签名对照表
所属类型 | 对相签名(sig) | 示例 |
boolean | Z | |
char | C | |
short | S | |
byte | B | |
int | I | |
long | J | |
float | F | |
double | D | |
void | V | |
object | L开发 ,用 / 分隔包的完整类名。 | 例如 String,则 sig : Ljava/lang/String; object : Ljava/lang/Object |
Array | 已 [ 开头,在加上数组的类型名。
| 例如 int[] —> [I int[][] —> [[I |
二、访问 java 静态成员变量:
这次使用 静态的native 方法:
public class NdkUtils {
// 静态属性 方法
public static String name1="小红";
public native static String getStaticAccessFiled();
static {
System.loadLibrary("native-lib");
}
}
native-lib.cpp
#include <jni.h>
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_cf8_1012_ndk_NdkUtils_getStaticAccessFiled(JNIEnv *env, jclass jcla) {
jfieldID jfieldID1 = env->GetStaticFieldID(jcla, "name1", "Ljava/lang/String;");
jstring jstring1 = (jstring) env->GetStaticObjectField(jcla, jfieldID1);
return jstring1;
}
MainActivity.class 中调用:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv1 = (TextView) findViewById(R.id.sample_text1);
tv1.setText(NdkUtils.getStaticAccessFiled());
}
}
运行结果:
三、访问java 中的方法
注: 方法的签名 是有规律的,需要结合成员变量的签名
格式: (参数类型)返回值类型
例如: public int add(int a,int b){}
签名为 : (II)I
JNI 调用java方法的 方法名格式 : Call<Type>Method() 例如 :CallIntMethod()
JINI调用静态java方法的 方法名格式:CallStatic<Type>Method() 例如 :CallStaticIntMethod()
NdkUtild.class
import java.util.Random;
public class NdkUtils {
// 随机数方法
public int getRandom(int i) {
return new Random().nextInt(i);
}
public native int accessMethod();
static {
System.loadLibrary("native-lib");
}
}
native.cpp
extern "C"
JNIEXPORT jint JNICALL Java_com_example_cf8_1012_ndk_NdkUtils_accessMethod
(JNIEnv *env, jobject jobj) {
// 获取 jclass 对象
jclass clazz = env->GetObjectClass(jobj);
// 根据 jclass 方法名 方法签名 获取方法的id
jmethodID jmethodID1 = env->GetMethodID(clazz, "getRandom", "(I)I");
// 调用 java 中的方法:获取200 以内的随机数
jint jint1 = env->CallIntMethod(jobj, jmethodID1, 200);
return jint1;
}
四、访问Java构造方法
NdkUtils.class
public class NdkUtils {
/**
* 访问 Date 类的 getTime() 方法
* Date date=new Date();
* long l=date.getTime();
*/
public native long accessCoustomer();
static {
System.loadLibrary("native-lib");
}
}
访问java 中的 java.util.Date 类
jclass clazzz = Findclass("包名+类名"):
native.cpp
/**
* 访问 java 中 java.util.Date 的构造方法
* */
extern "C"
JNIEXPORT jlong JNICALL
Java_com_example_cf8_1012_ndk_NdkUtils_accessCoustomer(JNIEnv *env, jobject instance) {
// 访问 java 中 java.util.Date 的构造方法
jclass clazz = env->FindClass("java/util/Date");
//注意 构造方法的 name固定为 "<init>"
jmethodID customerId = env->GetMethodID(clazz, "<init>", "()V");
// 实例化一个Date
jobject obj = env->NewObject(clazz, customerId);
// 调用Date 的方法
jmethodID methodId = env->GetMethodID(clazz, "getTime", "()J");
// 调用方法,获取返回值 long getTime();
jlong jlong1 = env->CallLongMethod(obj, methodId);
return jlong1;
}
Demo 下载地址:https://download.youkuaiyun.com/my