diff --git a/Cargo.lock b/Cargo.lock index d1a0bcc01acd..58cfcd679261 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4100,7 +4100,9 @@ version = "0.41.0" dependencies = [ "bytes", "cbindgen", + "once_cell", "opendal", + "tokio", ] [[package]] diff --git a/bindings/c/Cargo.toml b/bindings/c/Cargo.toml index 04a7205e3148..a0f31bc75f9b 100644 --- a/bindings/c/Cargo.toml +++ b/bindings/c/Cargo.toml @@ -37,3 +37,5 @@ cbindgen = "0.25.0" [dependencies] bytes = "1.4.0" opendal.workspace = true +tokio = { version = "1.27", features = ["fs", "macros", "rt-multi-thread"] } +once_cell = "1.17.1" diff --git a/bindings/c/src/lib.rs b/bindings/c/src/lib.rs index 013e2a307359..edaef1161f8b 100644 --- a/bindings/c/src/lib.rs +++ b/bindings/c/src/lib.rs @@ -35,6 +35,7 @@ use std::str::FromStr; use ::opendal as od; use error::opendal_error; +use once_cell::sync::Lazy; use result::opendal_result_list; use result::opendal_result_operator_new; use types::opendal_blocking_lister; @@ -47,6 +48,26 @@ use crate::types::opendal_metadata; use crate::types::opendal_operator_options; use crate::types::opendal_operator_ptr; +static RUNTIME: Lazy = Lazy::new(|| { + tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .unwrap() +}); + +fn build_operator(schema: od::Scheme, map: HashMap) -> od::Result { + let mut op = match od::Operator::via_map(schema, map) { + Ok(o) => o, + Err(e) => return Err(e), + }; + if !op.info().full_capability().blocking { + let runtime = + tokio::runtime::Handle::try_current().unwrap_or_else(|_| RUNTIME.handle().clone()); + let _guard = runtime.enter(); + op = op.layer(od::layers::BlockingLayer::create().expect("blocking layer must be created")); + } + Ok(op) +} /// \brief Construct an operator based on `scheme` and `options` /// /// Uses an array of key-value pairs to initialize the operator based on provided `scheme` @@ -121,23 +142,21 @@ pub unsafe extern "C" fn opendal_operator_new( } } - let op = match od::Operator::via_map(scheme, map) { - Ok(o) => o.blocking(), + match build_operator(scheme, map) { + Ok(op) => { + let op = opendal_operator_ptr::from(Box::into_raw(Box::new(op.blocking()))); + opendal_result_operator_new { + operator_ptr: Box::into_raw(Box::new(op)), + error: std::ptr::null_mut(), + } + } Err(e) => { let e = opendal_error::from_opendal_error(e); - let result = opendal_result_operator_new { + opendal_result_operator_new { operator_ptr: std::ptr::null_mut(), error: Box::into_raw(Box::new(e)), - }; - return result; + } } - }; - - // this prevents the operator memory from being dropped by the Box - let op = opendal_operator_ptr::from(Box::into_raw(Box::new(op))); - opendal_result_operator_new { - operator_ptr: Box::into_raw(Box::new(op)), - error: std::ptr::null_mut(), } }