(四)NDK开发之 java 与C/C++ 代码互相调用

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)示例
booleanZ 
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

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值