Flutter C++ 与 dart::ffi 的绑定

2024-03-03

我正在尝试为 C++ 代码编写一个包装器包,在我们的应用程序中进行一些数据分析。 我找到了这个很棒的帖子 https://stackoverflow.com/a/61597535/17552354这显示了做到这一点所需的主要步骤。我更像是一个 C/C++ 编码员,所以我有点卡住了,我不明白我做错了什么?

这是 analysis.hpp

#include <memory>
#include <vector>

struct int_array
{
    int* array;
    int len;
};

class cpp_analyses
{
public:
        cpp_analyses();
        ~cpp_analyses() = default;

        int_array get_header_index(int_array idx_list_input);
};

对应的analysis.cpp

#include "analyses.hpp"

cpp_analyses::cpp_analyses()
{

}

int_array cpp_analyses::get_header_index(int_array idx_list_input)
{
        int_array out;

        out.array = new int[2];
        out.len = 2;

        out.array[0] = 1;
        out.array[1] = 2;

        return out;
}

这是 analysis-adapter.hpp

#include "analyses.hpp"

#define EXPORT extern "C" __attribute__((visibility("default"))) __attribute__((used))

EXPORT void* initialize_analyses();
EXPORT int_array  analyses_get_index(void *ptr, struct int_array in_idx);

对应的源文件analysis_adapter.cpp

#include "analyses-adapter.hpp"

void* initialize_analyses()
{
        return new cpp_analyses;
}

int_array  analyses_get_index(void *ptr, struct int_array in_idx)
{
        auto typed_ptr = static_cast<cpp_analyses*>(ptr);
        return typed_ptr->get_header_index(in_idx);
}

在飞镖方面:

import 'dart:ffi';
import 'package:ffi/ffi.dart';

class IntArray extends Struct {
  external Pointer<Int32> data;

  @Int32()
  external int length;
}

typedef _example_init_analyses = Pointer<Void> Function();
typedef _analyses_get_saccades_index = IntArray Function(Pointer<Void> obj, IntArray input);

class Analyses {
        static late DynamicLibrary nativeApiLib;
        external Pointer<Void> _nativeInstance;
        external _analyses_index analyses_index;

        Analyses() {
                nativeApiLib =(DynamicLibrary.open('libanalyses.so')); // android and linux
                _example_init_analyses _initialize_analyses = nativeApiLib.lookup<NativeFunction<_example_init_analyses>>('initialize_analyses').asFunction();
                _nativeInstance = _initialize_analyses();

                analyses_index = nativeApiLib.lookup<NativeFunction<_analyses_index>>('analyses_get_index').asFunction();
        }

        IntArray get_saccades_index(IntArray input)
        {
                return analyses_index(_nativeInstance, input);
        }
}

最后在main.dart中

import 'package:flutter/material.dart';
import 'package:analyses/analyses.dart';

void main() {
        Analyses OBJ = new Analyses();
        IntArray TMP = IntArray();

        TMP.length = 2;

        IntArray TMP_second = OBJ.get_index(TMP);
}

整个代码构建没有问题。然而,当我尝试运行代码时,它抱怨这样一个事实:

#0 NoSuchMethodError._throwNew (dart:core-patch/errors_patch.dart:222:5)

#1 Analyses._nativeInstance=(包:analysis/ncapp_analysiss.dart)

我不明白我哪里做错了。任何帮助将不胜感激! 谢谢

EDIT根据要求,请查看完整的堆栈跟踪

Tried calling: _nativeInstance=
#0      NoSuchMethodError._throwNew (dart:core-patch/errors_patch.dart:222:5)
#1      Analyses._nativeInstance= (package:analyses/analyses.dart)
#2      new Analyses (package:analyses/analyses.dart:22:17)
#3      main (package:analyses/main.dart:5:33)
#4      _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:130:25)
#5      _rootRun (dart:async/zone.dart:1426:13)
#6      _CustomZone.run (dart:async/zone.dart:1328:19)
#7      _runZoned (dart:async/zone.dart:1861:10)
#8      runZonedGuarded (dart:async/zone.dart:1849:12)
#9      _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:126:5)
#10     _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)
#11     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)

如果我去掉前面的外部指针_nativeInstance;,我无法编译:

ERROR: lib/ncapp_analyses.dart:16:23: Error: Field '_nativeInstance' should be initialized because its type 'Pointer<Void>' doesn't allow null.
ERROR:  - 'Pointer' is from 'dart:ffi'.
ERROR:  - 'Void' is from 'dart:ffi'.
ERROR:         Pointer<Void> _nativeInstance;
ERROR:                       ^^^^^^^^^^^^^^^

首先,您需要将代表共享对象的 Dart 类与代表 C++ 类的 Dart 类分开。

第一个将包含共享库引用和查找的函数;第二个将只包含Pointer<Void>到你的 C++ 类的实例 - 每个实例都会有一个(并且当你完成该特定的 C++ 类实例时,这将是你释放的东西)。

例如:

import 'dart:ffi';

class SoLibrary {
  factory SoLibrary() {
    // make it a singleton
    _instance ??= SoLibrary._();
    return _instance!;
  }

  SoLibrary._() {
    // todo - check for Platform type
    _nativeApiLib = DynamicLibrary.open('libanalyses.so');
  }

  static SoLibrary? _instance;

  late DynamicLibrary _nativeApiLib;
  late final Pointer<Void> Function() _newAnalyses = _nativeApiLib
      .lookupFunction<Pointer<Void> Function(), Pointer<Void> Function()>(
          'initialize_analyses');
}

class Analyses {
  Pointer<Void> _nativeInstance;

  Analyses() : _nativeInstance = SoLibrary()._newAnalyses();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flutter C++ 与 dart::ffi 的绑定 的相关文章

  • 通过另一个列表更新列表(linq)

    我有类 Data 的对象列表 如下所示 class Data int code string name DateTime date update 我还有另一个课程列表 例如 class RefCodes int old code int n
  • OpenGL缓冲区更新[重复]

    这个问题在这里已经有答案了 目前我正在编写一个模拟水的程序 以下是我所做的步骤 创建水面 平面 创建VAO 创建顶点缓冲区对象 在其中存储法线和顶点 将指针绑定到此 VBO 创建索引缓冲区对象 然后我使用 glDrawElements 渲染
  • 如何调试在发布版本中优化的变量

    我用的是VS2010 我的调试版本工作正常 但我的发布版本不断崩溃 因此 在发布版本模式下 我右键单击该项目 选择 调试 然后选择 启动新实例 此时我看到我声明的一个数组 int ma 4 1 2 8 4 永远不会被初始化 关于可能发生的事
  • make_shared<>() 中的 WKWYL 优化是否会给某些多线程应用程序带来惩罚?

    前几天我偶然看到这个非常有趣的演示 http channel9 msdn com Events GoingNative GoingNative 2012 STL11 Magic Secrets作者 Stephan T Lavavej 其中提
  • 如何在Flutter中使用多个ChangeNotifierProvider?

    我最近开始使用provider对于我的状态管理 我知道如何一次使用一个 class Home extends StatelessWidget override Widget build BuildContext context return
  • 判断串口是普通COM还是SPP

    我正在寻找一种方法来确定 COM 是标准 COM 还是 SPP COM 也称为 COM 设备的电缆替换蓝牙适配器 我有一个可以在 USB COM gt USB 和蓝牙下工作的设备 并且蓝牙接口可以与 SPP 一起工作 我目前正在使用Syst
  • C 类型命名约定,_t 或 ALLCAPS

    我一直想知道是否有任何命名约定 例如何时对类型使用全部大写以及何时追加 t 什么时候不使用任何东西 我知道当时 K R 发布了各种有关如何使用 C 的文档 但我找不到任何相关内容 在 C 标准库类型中 t看起来漂亮占主导地位 time t
  • 提升mapped_file_source、对齐方式和页面大小

    我正在尝试在性能很重要的上下文中解析一些大小高达几百兆字节的文本文件 因此我使用 boostmapped file source 解析器期望源以空字节终止 因此我想检查文件大小是否是页面大小的精确倍数 如果是 则使用较慢的非内存映射方法 我
  • 检测 TextBox 中的 Tab 键按下

    I am trying to detect the Tab key press in a TextBox I know that the Tab key does not trigger the KeyDown KeyUp or the K
  • 如何增加ofstream的缓冲区大小

    我想增加 C 程序的缓冲区大小 以便它不会过于频繁地写入 默认缓冲区是 8192 字节 我尝试使用 pubsetbuf 将其增加到 200K 原始代码 ofstream fq fastq1 cstr ios out fastq1 is a
  • “没有合适的默认构造函数可用”——为什么会调用默认构造函数?

    我已经查看了与此相关的其他一些问题 但我不明白为什么在我的情况下甚至应该调用默认构造函数 我可以只提供一个默认构造函数 但我想了解它为什么这样做以及它会产生什么影响 error C2512 CubeGeometry no appropria
  • 将 2 个字节转换为整数

    我收到一个 2 个字节的端口号 最低有效字节在前 我想将其转换为整数 以便我可以使用它 我做了这个 char buf 2 Where the received bytes are char port 2 port 0 buf 1 port
  • 在 C++ 代码 gdb 中回溯指针

    我在运行 C 应用程序时遇到段错误 在 gdb 中 它显示我的一个指针位置已损坏 但我在应用程序期间创建了 10 万个这样的对象指针 我怎样才能看到导致崩溃的一个 我可以在 bt 命令中执行任何操作来查看该指针的生命周期吗 谢谢 鲁奇 据我
  • 将日期时间显示为 MM/dd/yyyy HH:mm 格式 C#

    在数据库中 日期时间以 MM dd yyyy HH mm ss 格式存储 但是 我想以 MM dd yyyy HH mm 格式显示日期时间 我通过使用 String Format 进行了尝试 txtCampaignStartDate Tex
  • 不使用放置 new 返回的指针时的 C++ 严格别名

    这可能会导致未定义的行为吗 uint8 t storage 4 We assume storage is properly aligned here int32 t intPtr new void storage int32 t 4 I k
  • 与 Entity Framework Core 2.0 的一对零关系

    我正在使用 C 和 NET Framework 4 7 将 Entity Framework 6 1 3 Code First 库迁移到 Entity Framework Core 我一直在用 Google 搜索 Entity Framew
  • 初始化列表在 VC10 中不起作用

    我在 VC 2010 中编写了这个程序 class class1 public class1 initializer list
  • 运行 xunit 测试时无法将输出打印到控制台窗口

    public class test2InAnotherProject private readonly ITestOutputHelper output public test2InAnotherProject ITestOutputHel
  • 如何知道 HTTP 请求标头值是否存在

    我确信这很简单 但是却让我感到厌烦 我在 Web 应用程序中使用了一个组件 它在 Web 请求期间通过添加标头 XYZComponent true 来标识自身 我遇到的问题是 如何在视图中检查此组件 以下内容不起作用 if Request
  • IDisposable 的显式实现

    虽然有很多关于IDisposable在 SO 上找到 我还没有找到答案 我通常遵循这样的做法 当我的一个班级拥有一个IDisposable对象然后它也实现IDisposable并打电话Dispose在拥有的对象上 然而最近我遇到了一个类 它

随机推荐