使用 dart:ffi 到 Flutter 的 C dll 返回超过 4000 个对象的问题[已关闭]

问题描述 投票:0回答:1

我正在实现一个 C 代码,该代码必须返回超过 4000 个自定义结构条目给 flutter 应用程序。该代码在 1000 个条目下运行良好,但当它返回 4000 左右时,flutter 应用程序崩溃并出现以下错误:

这是C结构体代码:

struct Win32ReadFileResult {
    int result = 0;
    int length = 0;
    list<Win32ReadFile> files = {};
};

这是该结构的 flutter 类:

base class Win32ReadFileResult extends Struct {
    @Uint32()
    external int result;
    @Uint32()
    external int length;
    @Array(1000)
    external Array<Win32ReadFile> files;
}

如果我将

@Array(1000)
注释更改为
@Array(4000)
,应用程序在调用 C 程序时会崩溃。

我不知道这是否是返回在 C dll 中创建的对象列表的最佳方法,或者也许我在 flutter 中的结构定义中有一些错误。

c++ c flutter winapi dart-ffi
1个回答
0
投票

您没有提供有关您的问题的太多背景信息,但以下是一些可观察到的问题:

1.这个

Win32ReadFileResult
结构绝对不是 C。基于
list<Win32ReadFile>
,我假设您使用了 C++ 中的
std:list
容器,并全局导入了
std
命名空间。不要通过结构体跨越语言边界传递 C++ 类,特别是如果它们需要 C! dart 应该如何知道类的内存布局?

2.我怀疑

std:list
@Array
对于您的用例是否正确。 cppreference 说:

std::list 是一个容器,支持从容器中的任何位置恒定时间插入和删除元素。不支持快速随机访问。它通常被实现为双向链表。

因此,您使用的容器甚至不需要像数组那样将元素存储在连续的内存块中。另一方面,dart ffi 文档 说:

数组 - 固定大小的项目数组。

据我所知,您的

std:list
是动态调整大小的,所以如果您指定列表中只有 2000 个元素的
@Array(4000)
会发生什么?
@Array
适用于
char[10]
等结构体字段,但不适用于列表。

C端修复方法:

将指针传递给元素

files
和元素计数
length
。将元素存储在连续的内存块中,可以使用
new
进行分配。使用
delete
提供再次释放内存的功能。例如:

struct Win32ReadFileList {
    int result = 0;
    int length = 0;
    Win32ReadFile* files = nullptr;
};

Win32ReadFileList GetReadFileList(...) {
  Win32ReadFileList fileList;
  fileList.files = new Win32ReadFile[...]();
  return fileList;
}

void FreeReadFileList(Win32ReadFileList fileList) {
  delete[] fileList.files;
}

如何修复 Dart 端:

使用

Pointer<Win32ReadFile>
代替
Array<Win32ReadFile>
并使用元素指针和元素计数访问
Win32ReadFile
元素。我目前不知道这在 dart 中是如何完成的,因为我从未使用过 dart ffi。

© www.soinside.com 2019 - 2024. All rights reserved.