Closed canewsin closed 2 years ago
Callbacks in dart have to be called synchronously. For asynchronous notifications a SendPort needs to be used. Futures and Streams use SendPort to notify dart when they're ready to be polled. If you need to go with a callback style API the way to do it would be using Future.then method which will be called when the future completes.
@dvc94ch One More Thing Could Provide What Rust Types are Supported for Code Gen?
Callbacks in dart have to be called synchronously. For asynchronous notifications a SendPort needs to be used. Futures and Streams use SendPort to notify dart when they're ready to be polled. If you need to go with a callback style API the way to do it would be using Future.then method which will be called when the future completes.
How to pass a Sync Function, could you provide some example?
don't quite follow. the idea is to use futures and streams with the flutter FutureBuilder
and StreamBuilder
. how exactly are you using callbacks?
Previously I did like this Dart :
late final _handle_eventPtr = _lookup<
ffi.NativeFunction<
ffi.Int32 Function(
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(ffi.Pointer<Utf8>)>>)>>('event_loop');
late final _handle_event = _handle_eventPtr.asFunction<
int Function(
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<Utf8>)>>)>();
int handleEventGen(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<Utf8>)>>
callback,
) {
return _handle_event(
callback,
);
}
pub extern "C" fn event_loop(callback: extern "C" fn(line: *const c_char)) -> u8 {
let runtime = unsafe { RUNTIME.as_mut() };
if let None = config {
return 4 as u8;
}
let config = config.unwrap();
.....
match (runtime, swarm) {
(Some(runtime), Some(swarm)) => {
runtime.block_on(async move {
loop {
...
callback(something_here)// This is continue to run;
}
});
0 as u8
}
(None, None) => 1 as u8,
(Some(_), None) => 2 as u8,
(None, Some(_)) => 3 as u8,
}
}
calling :
void callback(Pointer<Utf8> str) {
// print(Utf8.fromUtf8(str));
print(str.toDartString());
}
void attachListener() {
var result = handleEventGen(Pointer.fromFunction(cb));
var result = 0;
if (result == 0) {
print("Success");
}
}
well you can do that much easier now. swarm implements stream so you can do something like the following:
object SwarmEvent {
fn to_string() -> String;
}
object Swarm {
fn subscribe() -> Stream<SwarmEvent>;
}
pub struct SwarmEvent(libp2p_swarm::SwarmEvent);
impl SwarmEvent {
pub fn to_string(&self) -> String {
...
}
}
pub struct Swarm(libp2p_swarm::Swarm);
impl Swarm {
pub fn subscribe(&self) -> impl Stream<Item = SwarmEvent> {
...
}
}
StreamBuilder(
stream: swarm.subscribe(),
builder: (context, snapshot) {
if (snapshot != null) {
return Text(snapshot.toString());
} else {
return Text("loading");
}
}
Does that help? closing for now
Since I was just started with Rust, I had zero knowledge about streams tried to browse some examples nothing helped.
well what you want to do is spawn the swarm in a background task (because polling it requires &mut self) using something like this:
let (tx, rx) = futures::mpsc::unbounded();
async_global_executor::spawn(async move {
let mut listeners = vec![];
loop {
futures::select! {
res = rx.next() => {
if let Some(ch) = res {
listeners.push(ch);
}
}
res = swarm.next() => {
if let Some(event) = res {
listeners.retain(|tx| tx.unbounded_send(event.clone()).is_ok());
}
}
}}
});
object SwarmEventExt {
fn to_string() -> string;
}
object SwarmExt {
fn subscribe() -> Stream<SwarmEventExt>;
}
pub struct SwarmEventExt(NetworkSwarmEvent);
impl SwarmEventExt {
pub fn to_string(&self) -> String {
format!("{:?}", self.0)
}
}
///Is this required ?
impl Stream for SwarmEventExt {
type Item = SwarmEventExt;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
///Not figured how to implemen.
// Poll::Ready(Some(SwarmEventExt(self.0.poll_next(cx)?)))
Poll::Ready(None)
}
}
pub struct SwarmExt(Swarm<DecentNetworkBehaviour>);
use libp2p::futures::Stream;
// use streams::SwarmEventExt;
impl SwarmExt {
///it's our custom type right ?
pub fn subscribe(&mut self) -> impl Stream<Item = SwarmEvent> {
//impl Stream<Item = SwarmEventExt>
let runtime = tokio::runtime::Runtime::new();
let swarm: Swarm<DecentNetworkBehaviour> = self.0;
let s = runtime.unwrap().block_on(async {
let a = swarm.select_next_some().await;
}); unimplemented!()
}
}
oh just seen your comment
Previously with my implemetation I passed a pointer to rust function from dart, rust make the callback when needed and invoke such function, how to run a callback with this lib.