如何在Rust FFI库中重用时雄运行时

0kjbasz6  于 2023-06-30  发布在  其他
关注(0)|答案(4)|浏览(136)

我想为sn_api库编写一个FFI Package 器,其中包含async函数。它将用于用Red编写的单线程非异步代码中。
found,简单的方法是在每个导出的函数中使用Runtime::new().unwrap().block_on(...),虽然它涉及到大量创建新的时雄运行时,似乎太重了,无法在每次调用时运行:

  1. use std::os::raw::c_char;
  2. use std::ffi::{CString, CStr};
  3. use sn_api::{BootstrapConfig, Safe};
  4. use tokio::runtime::Runtime;
  5. #[no_mangle]
  6. pub extern "C" _safe_connect(ptr: *const Safe, bootstrap_contact: *const c_char) {
  7. assert!(!ptr.is_null());
  8. let _safe = unsafe {
  9. &*ptr
  10. };
  11. let bootstrap_contact = unsafe {
  12. CStr::from_ptr(bootstrap_contact)
  13. }
  14. let mut bootstrap_contacts = BootstrapConfig::default();
  15. bootstrap_contacts.insert(bootstrap_contact.parse().expect("Invalid bootstrap address"));
  16. // how to reuse the Runtime in other functions?
  17. Runtime::new().unwrap().block_on(_safe.connect(None, None, Some(bootstrap_contacts)));
  18. }

是否可以在一个通用的Runtime上运行所有的异步函数?我想这需要创建一些单例/全局变量,但我的库是用crate-type = ["cdylib"]编译的,这似乎不是全局变量的好地方。最好的办法是什么?

t5zmwmid

t5zmwmid1#

我已经决定了一种方法,我创建了一个时雄Runtime,然后将其传递给每个包含异步代码的FFI函数调用:

  1. use std::os::raw::c_char;
  2. use std::ffi::{CString, CStr};
  3. use sn_api::{BootstrapConfig, Safe};
  4. use tokio::runtime::Runtime;
  5. #[no_mangle]
  6. pub extern "C" fn init_runtime() -> *mut Runtime {
  7. Box::into_raw(Box::new(Runtime::new().unwrap()))
  8. }
  9. #[no_mangle]
  10. pub extern "C" _safe_connect(rt_ptr: *mut Runtime, safe_ptr: *mut Safe, bootstrap_contact: *const c_char) {
  11. assert!(!safe_ptr.is_null());
  12. assert!(!rt_ptr.is_null());
  13. let bootstrap_contact = unsafe {
  14. CStr::from_ptr(bootstrap_contact)
  15. }
  16. let mut bootstrap_contacts = BootstrapConfig::default();
  17. bootstrap_contacts.insert(bootstrap_contact.parse().expect("Invalid bootstrap address"));
  18. unsafe {
  19. let _safe = &mut *safe_ptr;
  20. let rt = &mut *rt_ptr;
  21. rt.block_on(_safe.connect(None, None, Some(bootstrap_contacts))).unwrap();
  22. }
  23. }
展开查看全部
r8xiu3jd

r8xiu3jd2#

使用静态变量保持运行库对函数调用的可访问性。

  1. use once_cell::sync::Lazy;
  2. use tokio::runtime::{self, Runtime};
  3. static RUNTIME: Lazy<Runtime> = Lazy::new(|| {
  4. runtime::Builder::new_multi_thread()
  5. .enable_io()
  6. .build()
  7. .unwrap()
  8. });
8nuwlpux

8nuwlpux3#

我也面临着同样的问题。这是我的削减:export-tokio-to-lib

plugin.rs:

  1. use async_ffi::{FfiFuture, FutureExt};
  2. use tokio::runtime::Handle;
  3. /// # Safety
  4. #[no_mangle]
  5. pub unsafe extern "C" fn test(arg: f32, handle: *const Handle) -> FfiFuture<safer_ffi::String> {
  6. let handle = &*handle;
  7. async move {
  8. let _enter = handle.enter();
  9. tokio::time::sleep(std::time::Duration::from_secs_f32(arg)).await;
  10. format!("slept {arg} secs").into()
  11. }
  12. .into_ffi()
  13. }
展开查看全部
lbsnaicq

lbsnaicq4#

试试这个
由此:

  1. #[tokio::main]
  2. async fn main() {
  3. println!("hello");
  4. }

转化为:

  1. fn main() {
  2. let mut rt = tokio::runtime::Runtime::new().unwrap();
  3. rt.block_on(async {
  4. println!("hello");
  5. })
  6. }

参考:https://tokio.rs/tokio/tutorial/hello-tokio#async-main-function

展开查看全部

相关问题