【Flutter跨平台插件开发】如何实现kotlin跟C++的相互调用

【Flutter跨平台插件开发】如何实现kotlin跟C++的相互调用

kotlin 调 c++

在 Kotlin 中,可以使用 JNI (Java Native Interface) 来调用 C++ 代码

调用步骤:

  1. 创建 C++ 文件并实现函数。
// 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 中声明需要调用的 native 函数并加载 native 库。
class MyClass {external fun myFunction(): Stringcompanion object {init {System.loadLibrary("example") // example是库的名字}}
}
  1. 调用示例
val myClass = MyClass()
println(myClass.myFunction()) // 输出 "Hello from C++"

Flutter 插件项目的例子

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

  1. 首先,在 Flutter 插件的 android 目录下创建一个 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 关键字来声明 native 方法。
class MyPlugin: FlutterPlugin, MethodCallHandler {// ...external fun myNativeMethod(): Stringinit {System.loadLibrary("native-lib")}// ...
}
  1. 最后,在 C++ 代码中实现函数。
#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++ 函数的名称必须遵循特定的格式:Java_包名_类名_方法名。在这个例子中,Java_com_example_MyClass_myFunction 对应于 com.example.MyClass 类的 myFunction 方法。

c++ 调 kotln

在 Kotlin 中,可以使用 JNI (Java Native Interface) 来设置回调到 C++ 代码。

同步调用(这个需要kotlin先调到cpp,cpp再调回来,都是同步操作)

  1. 在 Kotlin 中创建一个接口,该接口将被 C++ 代码调用。
interface Callback {fun onEvent(event: String)
}
  1. 创建一个 native 函数,kotlin 的回调函数将通过这个native函数,传给cpp
class MyClass {private var callback: Callback? = nullfun 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++ 代码中实现 triggerEvent 函数,从参数中获取 onEvent 方法并调用。
#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 foundjstring message = env->NewStringUTF("Hello from C++");env->CallVoidMethod(instance, mid, message);
}

在这个例子中,triggerEvent 函数在 C++ 代码中被调用,然后它调用 Kotlin 中的 onEvent 方法,该方法然后调用 Callback 接口的 onEvent 方法。

方法签名

在 JNI (Java Native Interface) 中,“(Ljava/lang/String;)V” 是一个方法签名,用于描述方法的参数类型和返回值类型

这个签名可以被分解为以下部分:

  • 括号 “(” 和 “)”:括号内的内容描述了方法的参数类型。在这个例子中,“Ljava/lang/String;” 表示方法有一个参数,类型为 java.lang.String

  • “V”:这是方法的返回值类型。在 JNI 中,“V” 表示 void,也就是说这个方法没有返回值。

所以,“(Ljava/lang/String;)V” 这个签名表示的是一个接受一个 java.lang.String 参数并且没有返回值的方法。

其他一些常见的 JNI 类型签名包括:

  • “I”:表示 int
  • “J”:表示 long
  • “S”:表示 short
  • “B”:表示 byte
  • “C”:表示 char
  • “D”:表示 double
  • “F”:表示 float
  • “Z”:表示 boolean
  • “[I”:表示 int 数组
  • “Lfully/qualified/ClassName;”:表示 fully.qualified.ClassName 类型的对象

你可以在 JNI 文档中找到更多关于类型签名的信息。

异步回调

在 JNI 中,JNIEnv*jobject 通常不能直接保存起来用于异步回调。
这是因为:

  • JNIEnv* 是线程相关的,每个线程都有一个不同的 JNIEnv*。如果你在一个线程保存了 JNIEnv*,然后在另一个线程使用它,可能会导致问题。
  • 同样,jobject 是一个局部引用,它只在当前的 JNI 调用中有效,调用结束后就会被自动删除。

如果你需要在异步回调中使用这些对象,你需要做一些额外的步骤:

  1. 对于 JNIEnv*,你需要在回调的线程中通过 JavaVM* 获取一个新的 JNIEnv*。你可以在保存 JNIEnv* 的同时保存 JavaVM*,通过调用 JNIEnv->GetJavaVM(&jvm) 获取。

  2. 对于 jobject,你需要创建一个全局引用,这样它就可以跨越多个 JNI 调用。你可以通过调用 JNIEnv->NewGlobalRef(jobject) 来创建一个全局引用。记住在你不再需要这个全局引用时,需要调用 JNIEnv->DeleteGlobalRef(jobject) 来删除它,防止内存泄漏。

以下是一个简单的例子:

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后,这里参考上面同步调用的例子的实现jvm->DetachCurrentThread();
}

在这个例子中,Java_MyClass_init 是一个 JNI 方法,它保存了 JavaVM* 和一个全局引用。然后在 asyncCallback 中,我们获取了一个新的 JNIEnv*,并使用了全局引用。注意我们在回调结束时调用了 DetachCurrentThread,这是因为我们之前调用了 AttachCurrentThread。如果你在一个已经被附加到 JVM 的线程中调用回调,你不需要调用这两个方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/645206.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL 系列教程(二)

目录 SQL DELETE 语句 DELETE 语句 演示数据库 DELETE 实例 删除所有行 SQL TOP, LIMIT, ROWNUM 子句 TOP 子句 演示数据库 SQL TOP、LIMIT 和 ROWNUM 示例 SQL TOP PERCENT 实例 添加WHERE子句 SQL MIN() 和 MAX() 函数 MIN() 和 MAX() 函数 演示数据库 MIN() …

spring eureka集群相关问题

一、集群节点信息如何更新&#xff1f; EurekaServer节点启动的时候&#xff0c;DefaultEurekaServerContext.init()方法调用PeerEurekaNodes.start()方法&#xff0c;start方法中resolvePeerUrls()会从配置文件读取serviceUrl属性值获得集群最新节点信息&#xff0c;通过upda…

电池回收产业东风中,吉利科技集团如何先行一步?

随着绿色低碳可持续发展理念深入人心&#xff0c;全球能源变革和转型升级持续推进&#xff0c;新能源行业不断涌现新的机遇。 动力电池回收和再利用&#xff0c;就是近在眼前的“红利型”产业。 我国新能源汽车市场近年来爆发式增长&#xff0c;动力电池生产紧随电动车普及步…

【代码管理】TortoiseGit 图标没有显示

当TortoiseGit在Windows系统中没有正确显示文件和目录的图标状态时&#xff0c;可能的原因和解决方法如下&#xff1a; 原因与解决方案&#xff1a; TortoiseGit未集成到资源管理器&#xff1a; 请确保TortoiseGit已正确安装&#xff0c;并在安装过程中选择了“将TortoiseGit集…

C++区间覆盖(贪心算法)

假设有n个区间&#xff0c;分别是&#xff1a;[l1,r1], [l2,r2], [l3,r3].....[ln,rn] 从这n个区间中选出某些区间&#xff0c;要求这些区间满足两两不相交&#xff0c;最多能选出多少个区间呢&#xff1f; 基本思路&#xff1a; 按照右端点从小到大排序&#xff0c;再比较左端…

深度学习中RGB影像图的直方图均衡化python代码and对图片中指定部分做基于掩模的特定区域直方图均衡化

深度学习很重要的预处理步骤 就是需要对做直方图均衡化 其中主要分成灰度图以及RGB图的直方图均衡化 这俩的方法和代码不同 想要去看具体原理的朋友可以查看下面这篇博客的内容 写的很详细颜色直方图均衡化(https://www.cnblogs.com/wancy/p/17668345.html) 我们这个场景中会用…

【RT-DETR有效改进】FasterNet一种跑起来的主干网络( 提高FPS和检测效率)

前言 大家好&#xff0c;这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进&#xff0c;内容持续更新&#xff0c;每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本&#xff0c;同时修改内容也支持ResNet32、ResNet101和PP…

Google murmur3 hashString用法

如下为将String获取hashcode&#xff0c;转为Long的方法&#xff0c;主要是在海量数据的flink程序里&#xff0c;为了节省状态的存储空间&#xff0c;所以尝试用long来存储。 同样的还可以hash其他格式的数据。 评估了下&#xff0c;murmur3最高用的是128位的hash值&#xff…

圈子论坛社交实名制系统---H5小程序APP,三端源码交付,允许二开!PHP系统uni书写!

圈子系统是一种社会化网络平台&#xff0c;它的核心是以用户为中心&#xff0c;围绕用户的兴趣、爱好、经历和职业等因素&#xff0c;将具有相同特质的个体聚集起来&#xff0c;形成具有共同话题和兴趣的社交圈子。这样的系统旨在帮助用户拓宽社交范围&#xff0c;提升社交效率…

uniapp+vue开发微信小程序,image标签图片IOS可以正常回显,安卓回显不出

仅代表个人遇到的问题&#xff0c;仅代表个人遇到的问题&#xff0c;仅代表个人遇到的问题&#xff0c; 1.先说最快的解决方案&#xff0c;直接在src下面额外添加一段url&#xff0c;https://images.weserv.nl/?url&#xff0c; <imagestyle"width: 180rpx; height: 2…

封装 element el-date-picker时间选择区间

基于el-date-picker 处理满足项目需求。&#xff08;&#xff1a;最多选择7天&#xff09; 效果&#xff1a; 1 大于当前时间的以后日期禁选。2 选中时间的前后七天可选 &#xff08;最多可查询7天数据&#xff09;3 <template><section class"warning-contai…

FPGA硬件架构——具体型号是xc7k325tffg676-2为例

1.共如下图14个时钟域&#xff0c;XmYn(按坐标理解) 2.IOB(IOB为可编程输入输出单元,当然在普通Bank上的IOB附近还有很多时钟资源&#xff0c;例如PLL&#xff0c;MMCM资源。), 2.1 FPGA的Bank分为HP Bank和HR Bank&#xff0c;二者对电压的要求范围不同&#xff0c;HR支持更大…

Spark 的宽依赖和窄依赖

Apache Spark 中的依赖关系指的是转换操作&#xff08;transformations&#xff09;之间的依赖类型。这些依赖关系决定了任务是如何在集群上分布执行的。依赖关系分为两类&#xff1a;宽依赖&#xff08;Wide Dependency&#xff09;和窄依赖&#xff08;Narrow Dependency&…

orchestrator介绍3.2 命令行之orchestrator-client

orchestrator-client 是一个包装 API 调用的脚本&#xff0c;使用起来更方便。 它可以自动确定orchestrator的Leader角色&#xff0c;并在这种情况下将所有请求转发给Leader。 有了orchestrator-client&#xff1a; 不需要到处安装orchestrator的二进制文件&#xff1b;仅在…

2023龙信杯wp

打了好像70多分&#xff0c;没拿奖&#xff0c;因为一些众所周知的原因&#xff0c;复盘间隔时间太长了没什么印象了已经 案情简介 2023年9月&#xff0c;某公安机关指挥中心接受害人报案:通过即时通讯工具添加认识一位叫“周微”的女人&#xff0c;两人谈论甚欢&#xff0c;确…

大语言模型推理提速:TensorRT-LLM 高性能推理实践

作者&#xff1a;顾静 TensorRT-LLM 如何提升 LLM 模型推理效率 大型语言模型&#xff08;Large language models,LLM&#xff09;是基于大量数据进行预训练的超大型深度学习模型。底层转换器是一组神经网络&#xff0c;这些神经网络由具有 self-attention 的编码器和解码器组…

自然语言处理(NLP)的发展

自然语言处理的发展 随着深度学习和大数据技术的进步&#xff0c;自然语言处理取得了显著的进步。人们正在研究如何使计算机更好地理解和生成人类语言&#xff0c;以及如何应用NLP技术改善搜索引擎、语音助手、机器翻译等领域。 方向一&#xff1a;技术进步 自然语言处理&…

【算法专题】动态规划之简单多状态 dp 问题

动态规划3.0 动态规划 - - - 简单多状态 dp 问题1. 按摩师(打家劫舍Ⅰ的变形)2. 打家劫舍Ⅱ3. 删除并获得点数4. 粉刷房子5. 买卖股票的最佳时机含冷冻期6. 买卖股票的最佳时机含手续费7. 买卖股票的最佳时机Ⅲ8. 买卖股票的最佳时机Ⅳ 动态规划 - - - 简单多状态 dp 问题 1. …

【Java 设计模式】行为型之备忘录模式

文章目录 1. 定义2. 应用场景3. 代码实现结语 备忘录模式&#xff08;Memento Pattern&#xff09;是一种行为型设计模式&#xff0c;用于捕获一个对象的内部状态&#xff0c;以便稍后可以将该对象恢复到此状态。备忘录模式允许在不破坏封装性的前提下捕获和外部化对象的内部状…

Could not autowire. No beans of ‘RedisConnectionFactory‘ type found.已解决

springboot2.7.8 redis3.2.100 在springboot中 使用RedisConnectionFactory 出现这样的错误Could not autowire. No beans of ‘RedisConnectionFactory‘ type found. 只需要在pom.xml中加入 <!-- 整合redis --> <dependency> <groupId>org.springf…