国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Flutter跨平臺插件開發(fā)】如何實現(xiàn)kotlin跟C++的相互調(diào)用

這篇具有很好參考價值的文章主要介紹了【Flutter跨平臺插件開發(fā)】如何實現(xiàn)kotlin跟C++的相互調(diào)用。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

【Flutter跨平臺插件開發(fā)】如何實現(xiàn)kotlin跟C++的相互調(diào)用

kotlin 調(diào) c++

在 Kotlin 中,可以使用 JNI (Java Native Interface) 來調(diào)用 C++ 代碼

調(diào)用步驟:

  1. 創(chuàng)建 C++ 文件并實現(xiàn)函數(shù)。
// example.cpp
#include <jni.h>

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_MyClass_myFunction(JNIEnv* env, jobject /* this */) {
    return env->NewStringUTF("Hello from C++");
}
  1. 在 Kotlin 中聲明需要調(diào)用的 native 函數(shù)并加載 native 庫。
class MyClass {
    external fun myFunction(): String

    companion object {
        init {
            System.loadLibrary("example") // example是庫的名字
        }
    }
}
  1. 調(diào)用示例
val myClass = MyClass()
println(myClass.myFunction()) // 輸出 "Hello from C++"

Flutter 插件項目的例子

在 Flutter 插件中引用已有的 C++ 源碼需要以下步驟:

  1. 首先,在 Flutter 插件的 android 目錄下創(chuàng)建一個 CMakeLists.txt 文件,這個文件會告訴 CMake 如何編譯你的 C++ 代碼。
cmake_minimum_required(VERSION 3.4.1)

add_library( # Specifies the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp )
  1. 然后,在插件的 build.gradle 文件中啟用 CMake 并指定 CMakeLists.txt 文件的位置。
android {
    // ...

    defaultConfig {
        // ...

        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
    }

    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}
  1. 在 Kotlin 代碼中,可以使用 System.loadLibrary 來加載庫,并使用 external 關(guān)鍵字來聲明 native 方法。
class MyPlugin: FlutterPlugin, MethodCallHandler {
    // ...

    external fun myNativeMethod(): String

    init {
        System.loadLibrary("native-lib")
    }

    // ...
}
  1. 最后,在 C++ 代碼中實現(xiàn)函數(shù)。
#include <jni.h>

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_MyPlugin_myNativeMethod(JNIEnv* env, jobject /* this */) {
    // 你的代碼...
}
注意
  1. 需要使用 ndk-build 或者 CMake 來編譯 C++ 代碼,并將生成的庫放到 Android 項目的 jniLibs 目錄下。
  2. C++ 函數(shù)的名稱必須遵循特定的格式:Java_包名_類名_方法名。在這個例子中,Java_com_example_MyClass_myFunction 對應(yīng)于 com.example.MyClass 類的 myFunction 方法。

c++ 調(diào) kotln

在 Kotlin 中,可以使用 JNI (Java Native Interface) 來設(shè)置回調(diào)到 C++ 代碼。

同步調(diào)用(這個需要kotlin先調(diào)到cpp,cpp再調(diào)回來,都是同步操作)

  1. 在 Kotlin 中創(chuàng)建一個接口,該接口將被 C++ 代碼調(diào)用。
interface Callback {
    fun onEvent(event: String)
}
  1. 創(chuàng)建一個 native 函數(shù),kotlin 的回調(diào)函數(shù)將通過這個native函數(shù),傳給cpp
class MyClass {
    private var callback: Callback? = null

    fun setCallback(callback: Callback) {
        this.callback = callback
    }

    external fun triggerEvent()

    private fun onEvent(event: String) {
        callback?.onEvent(event)
    }

    companion object {
        init {
            System.loadLibrary("example")
        }
    }
}
  1. 在 C++ 代碼中實現(xiàn) triggerEvent 函數(shù),從參數(shù)中獲取 onEvent 方法并調(diào)用。
#include <jni.h>

extern "C" JNIEXPORT void JNICALL
Java_com_example_MyClass_triggerEvent(JNIEnv* env, jobject instance) {
    jclass cls = env->GetObjectClass(instance);
    jmethodID mid = env->GetMethodID(cls, "onEvent", "(Ljava/lang/String;)V");
    if (mid == nullptr) return; // method not found
    jstring message = env->NewStringUTF("Hello from C++");
    env->CallVoidMethod(instance, mid, message);
}

在這個例子中,triggerEvent 函數(shù)在 C++ 代碼中被調(diào)用,然后它調(diào)用 Kotlin 中的 onEvent 方法,該方法然后調(diào)用 Callback 接口的 onEvent 方法。

方法簽名

在 JNI (Java Native Interface) 中,“(Ljava/lang/String;)V” 是一個方法簽名,用于描述方法的參數(shù)類型和返回值類型

這個簽名可以被分解為以下部分:

  • 括號 “(” 和 “)”:括號內(nèi)的內(nèi)容描述了方法的參數(shù)類型。在這個例子中,“Ljava/lang/String;” 表示方法有一個參數(shù),類型為 java.lang.String。

  • “V”:這是方法的返回值類型。在 JNI 中,“V” 表示 void,也就是說這個方法沒有返回值。

所以,“(Ljava/lang/String;)V” 這個簽名表示的是一個接受一個 java.lang.String 參數(shù)并且沒有返回值的方法。

其他一些常見的 JNI 類型簽名包括:

  • “I”:表示 int
  • “J”:表示 long
  • “S”:表示 short
  • “B”:表示 byte
  • “C”:表示 char
  • “D”:表示 double
  • “F”:表示 float
  • “Z”:表示 boolean
  • “[I”:表示 int 數(shù)組
  • “Lfully/qualified/ClassName;”:表示 fully.qualified.ClassName 類型的對象

你可以在 JNI 文檔中找到更多關(guān)于類型簽名的信息。

異步回調(diào)

在 JNI 中,JNIEnv*jobject 通常不能直接保存起來用于異步回調(diào)。
這是因為:

  • JNIEnv* 是線程相關(guān)的,每個線程都有一個不同的 JNIEnv*。如果你在一個線程保存了 JNIEnv*,然后在另一個線程使用它,可能會導(dǎo)致問題。
  • 同樣,jobject 是一個局部引用,它只在當(dāng)前的 JNI 調(diào)用中有效,調(diào)用結(jié)束后就會被自動刪除。

如果你需要在異步回調(diào)中使用這些對象,你需要做一些額外的步驟:

  1. 對于 JNIEnv*,你需要在回調(diào)的線程中通過 JavaVM* 獲取一個新的 JNIEnv*。你可以在保存 JNIEnv* 的同時保存 JavaVM*,通過調(diào)用 JNIEnv->GetJavaVM(&jvm) 獲取。

  2. 對于 jobject,你需要創(chuàng)建一個全局引用,這樣它就可以跨越多個 JNI 調(diào)用。你可以通過調(diào)用 JNIEnv->NewGlobalRef(jobject) 來創(chuàng)建一個全局引用。記住在你不再需要這個全局引用時,需要調(diào)用 JNIEnv->DeleteGlobalRef(jobject) 來刪除它,防止內(nèi)存泄漏。

以下是一個簡單的例子:

JavaVM* jvm;
jobject globalObj;

JNIEXPORT void JNICALL Java_MyClass_init(JNIEnv* env, jobject obj) {
    env->GetJavaVM(&jvm);
    globalObj = env->NewGlobalRef(obj);
}

void asyncCallback() {
    JNIEnv* env;
    jvm->AttachCurrentThread(&env, NULL);

    // 有了env跟obj后,這里參考上面同步調(diào)用的例子的實現(xiàn)

    jvm->DetachCurrentThread();
}

在這個例子中,Java_MyClass_init 是一個 JNI 方法,它保存了 JavaVM* 和一個全局引用。然后在 asyncCallback 中,我們獲取了一個新的 JNIEnv*,并使用了全局引用。注意我們在回調(diào)結(jié)束時調(diào)用了 DetachCurrentThread,這是因為我們之前調(diào)用了 AttachCurrentThread。如果你在一個已經(jīng)被附加到 JVM 的線程中調(diào)用回調(diào),你不需要調(diào)用這兩個方法。文章來源地址http://www.zghlxwxcb.cn/news/detail-822279.html

到了這里,關(guān)于【Flutter跨平臺插件開發(fā)】如何實現(xiàn)kotlin跟C++的相互調(diào)用的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包