Android开发,JNI,NDK,C++和java代码互相调用方法

Android开发,JNI,NDK,C++和java代码互相调用方法

1.java,jni,c数据类型

java的数据类型不能直接给c使用,要通过jni转换。

比如String,要通过jni的jstring转换成c语言的char *,其他数据类型也是一样

实践

java层代码

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    private static final String TAG = "MainActivity";
    private String test = "test";

    public native String stringFromJNI();

    public native void test();

    private double num = 1;
    private final double num2 = 2;

    public native void doubleFromJNI();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
        Log.e(TAG, "onCreate: ");
        test();
        Log.e(TAG, "onCreate: 修改前 " + num2);
        doubleFromJNI();
        Log.e(TAG, "onCreate: 修改后 " + num2);

    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
}

jni

#include <jni.h>
#include <string>

#include <android/log.h>

#define TAG "testLog"

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}
//代码采用C语言编译
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_test(JNIEnv *env, jobject jobject1) {


}extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_doubleFromJNI(JNIEnv *env, jobject thiz) {
    jclass test = env->GetObjectClass(thiz);
//    jfieldID num = env->GetFieldID(test, "num", "D");
//
//    env->SetDoubleField(thiz,num, 444.5);


    jfieldID num2 = env->GetFieldID(test, "num2", "D");
    env->SetDoubleField(thiz, num2, 5555.5);

    LOGD("SSSSSSSSSSSSSS %d\n", 1312);
}

运行一下看看修改的num2的值

在这里插入图片描述

这个是java和jni通信的桥梁。

JNIEnv

看他源码

在这里插入图片描述

//当前语言是c++、
#if defined(__cplusplus)
typedef _JNIEnv JNIEnv;
typedef _JavaVM JavaVM;
#else
//当前语言是c语言
typedef const struct JNINativeInterface* JNIEnv;
typedef const struct JNIInvokeInterface* JavaVM;
#endif

指的是我们这个文件的后缀

在这里插入图片描述

最终

都是访问的这个结构体指针,C语言的

在这里插入图片描述

如果方法是静态的就是jclass,否则就是对象实例,

在这里插入图片描述

在这里插入图片描述

最终jni会打包到apk中成为一个so库

在这里插入图片描述

2.jni日志输出

日志库

#include <android/log.h>

#define TAG "testLog"

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);

在这里插入图片描述

运行

在这里插入图片描述

3.函数调用

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    private static final String TAG = "MainActivity";
    private String test = "test";

    public native String stringFromJNI();

    public native void test();

    private double num = 1;
    private double num2 = 2;

    public native void doubleFromJNI();
    //jni调用它
    public int addNum(int a, int b) {
        Log.e(TAG, "addNum: ");
        return a + b;
    }
    //
    public native void testAddNum();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
        Log.e(TAG, "onCreate: ");
        test();
        Log.e(TAG, "onCreate: 修改前 " + num2);
        doubleFromJNI();
        Log.e(TAG, "onCreate: 修改后 " + num2);
        testAddNum();
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
}

声明一个java函数一个jni函数

在这里插入图片描述

在java中调用我们的jni函数

在这里插入图片描述

jni中再反调用我们的java函数

extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_testAddNum(JNIEnv *env, jobject thiz) {
    jclass jclass1 = env->GetObjectClass(thiz);
    jmethodID add = env->GetMethodID(jclass1, "addNum", "(II)I");
    int jint = env->CallIntMethod(thiz, add, 2, 3);
    LOGD("============%d\n", jint);
}

输出

在这里插入图片描述

字符串函数

在这里插入图片描述

jni调用java字符串函数

extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_testAddNum(JNIEnv *env, jobject thiz) {
    /*jclass jclass1 = env->GetObjectClass(thiz);
    jmethodID add = env->GetMethodID(jclass1, "addNum", "(II)I");
    int jint = env->CallIntMethod(thiz, add, 2, 3);
    LOGD("============%d\n", jint);*/
    jclass jclass1 = env->GetObjectClass(thiz);
    jmethodID jmethodId = env->GetMethodID(jclass1, "getTestString",
                                           "(Ljava/lang/String;I)Ljava/lang/String;");
    jstring va = env->NewStringUTF("22222");
    jstring rrr = (jstring) env->CallObjectMethod(thiz, jmethodId, va, 222);
    const char *string = env->GetStringUTFChars(rrr,NULL);
    LOGD("==============%s\n", string);
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值