如何将本机空指针传递到Dart隔离-无需复制?
我正在为Dart公开一个音频库(C库)。要触发音频引擎,它需要几个初始化步骤(UI不阻塞),然后使用执行函数触发音频处理,这就是阻塞(音频处理是一项繁重的任务)。这就是我来读Dart分离物的原因 我的第一个想法是,我只需要在隔离中调用performance方法,但这似乎是不可能的,因为perform函数将引擎状态作为第一个参数-这个引擎状态是一个不透明的指针(dart:ffi中的指针)。当尝试使用compute函数将引擎状态传递给新的隔离时,Dart VM返回一个错误-它无法将C指针传递给隔离 我找不到一种方法将这些数据传递到隔离区,我认为这是由于主隔离区和我正在创建的隔离区的内存不同 因此,我可能应该在隔离中管理整个发动机状态,这意味着:如何将本机空指针传递到Dart隔离-无需复制?,dart,dart-isolates,dart-ffi,Dart,Dart Isolates,Dart Ffi,我正在为Dart公开一个音频库(C库)。要触发音频引擎,它需要几个初始化步骤(UI不阻塞),然后使用执行函数触发音频处理,这就是阻塞(音频处理是一项繁重的任务)。这就是我来读Dart分离物的原因 我的第一个想法是,我只需要在隔离中调用performance方法,但这似乎是不可能的,因为perform函数将引擎状态作为第一个参数-这个引擎状态是一个不透明的指针(dart:ffi中的指针)。当尝试使用compute函数将引擎状态传递给新的隔离时,Dart VM返回一个错误-它无法将C指针传递给隔离
- 创建引擎状态
- 使用一些选项(字符串)初始化它
- 触发执行功能
- 在运行时控制音频
指针engineState=createEngineState();
initEngine(engineState,参数字符串);
startEngine(房地产);
表演(不动产);
在运行时,由UI操作(如滑块值更改或按钮单击)触发:
setEngineControl(engineState,valueToSet);
双重控制值=getEngineControl(engineState);
引擎状态可以封装在一个类中,我认为它在这里并不重要。
无论它是一个类还是一个不透明的数据类型,我都找不到如何管理和保持这种状态,以及如何从主线程执行触发器(在隔离中处理)。有什么想法吗
提前,谢谢
PS:我注意到,在写作时,我的问题/解释可能不准确,我不得不说我在这里有点迷茫,因为我从未使用过Dart。如果缺少一些信息,请告诉我
4月24日编辑:
它似乎在隔离内部创建和管理对象状态。但主要问题并没有解决。因为perform方法在未完成时实际上是阻塞的,所以无法在隔离中仍然接收消息。
我首先想到的一个选项是使用performBlock方法,它只执行一块音频样本。像这样:
while(performBlock(engineState)){
//听留言,做点什么
}
但这似乎不起作用,这个过程仍然被阻止,直到音频性能完成。即使在隔离中的异步方法中调用此循环,它也会阻塞,并且不会读取任何消息
我现在考虑将主隔离中管理的指针
传递给另一个的可能性,该指针将是工作者(仅用于执行方法),然后能够从主隔离触发一些控制方法
Dart包提供了一个注册表子库来管理一些共享内存。但仍然不可能在隔离之间传递void指针
[错误:flatter/lib/ui/ui_dart_state.cc(157)]未处理的异常:无效参数:无法在隔离之间传递本机对象(来自dart:ffi),例如指针和结构
有没有人遇到过这种情况 可以获取此
指针作为数字指向的地址,并从此地址构造新的指针(请参阅和)。因为数字可以在隔离之间自由传递,所以这可以用来在它们之间传递本机指针
例如,在您的例子中,可以这样做(我使用颤振使示例更简单,但显然也可以显式使用Send/ReceivePort
s)
//要在回退隔离中使用的回调。
//返回新引擎的地址。
int initEngine(字符串参数){
指针engineState=createEngineState();
初始化引擎(引擎状态、参数);
startEngine(房地产);
返回。地址;
}
//要在回退隔离中使用的回调。
//使用给定的引擎执行任何需要的处理。
无效进程WithEngine(int engineStateAddress){
最终engineState=指针.fromAddress(engineStateAddress);
工艺(不动产);
}
void main(){
//在后台隔离中初始化引擎。
最终地址=计算(initEngine,“参数”);
final engineState=指针.fromAddress(地址);
//使用引擎在背景隔离中执行一些繁重的计算。
计算(processWithEngine、engineState.address);
}
我最终在音频循环本身内部处理回调
while(performAudio())
{
tasks.forEach((字符串键,列表值){
double val=getCallback(键);
value.forEach((int元素){
发送([element,val]);
});
});
}
其中“val”是要发送给回调的对象。int'value'的列表是回调索引的列表
假设音频循环使用512个样本的向量大小执行,则在处理每512个音频样本后,您将能够通过回调,这意味着每秒48000/512次(假设采样率为48000)。这种方法不是最好的,但它很有效,不过我还是要看看它在非常密集的处理环境中是否有效。在这里,它被认为是用于实时音频,但它也可以用于音频渲染
您可以在这里看到完整的代码:您不能只做整个过程吗?(创建指针,并与主控制器通信