diff --git a/bindings/c/include/opendal.h b/bindings/c/include/opendal.h index 68541f1cad7..a709c2fcfec 100644 --- a/bindings/c/include/opendal.h +++ b/bindings/c/include/opendal.h @@ -164,6 +164,11 @@ extern "C" { */ opendal_operator_ptr opendal_operator_new(const char *scheme); +/* + Free the allocated operator pointed by [`opendal_operator_ptr`] + */ +void opendal_operator_free(opendal_operator_ptr op_ptr); + /* Write the data into the path blockingly by operator, returns the error code OPENDAL_OK if succeeds, others otherwise @@ -195,7 +200,7 @@ struct opendal_result_read opendal_operator_blocking_read(opendal_operator_ptr o const char *path); /* - Frees the heap memory used by the [`Bytes`] + Frees the heap memory used by the [`opendal_bytes`] */ void opendal_bytes_free(const struct opendal_bytes *vec); diff --git a/bindings/c/src/lib.rs b/bindings/c/src/lib.rs index 8259f476b5a..33d4488dee4 100644 --- a/bindings/c/src/lib.rs +++ b/bindings/c/src/lib.rs @@ -72,6 +72,16 @@ pub unsafe extern "C" fn opendal_operator_new(scheme: *const c_char) -> opendal_ opendal_operator_ptr::from(op) } +/// Free the allocated operator pointed by [`opendal_operator_ptr`] +#[no_mangle] +pub extern "C" fn opendal_operator_free(op_ptr: opendal_operator_ptr) { + if op_ptr.is_null() { + return; + } + let _ = unsafe { Box::from_raw(op_ptr.get_ref_mut()) }; + // dropped +} + /// Write the data into the path blockingly by operator, returns the error code OPENDAL_OK /// if succeeds, others otherwise /// diff --git a/bindings/c/src/types.rs b/bindings/c/src/types.rs index fbc2cddf860..f3b40d8223f 100644 --- a/bindings/c/src/types.rs +++ b/bindings/c/src/types.rs @@ -41,10 +41,23 @@ impl opendal_operator_ptr { } } + /// Returns whether this points to NULL + pub(crate) fn is_null(&self) -> bool { + self.ptr.is_null() + } + /// Returns a reference to the underlying [`BlockingOperator`] pub(crate) fn get_ref(&self) -> &od::BlockingOperator { unsafe { &*(self.ptr) } } + + /// Returns a mutable reference to the underlying [`od::BlockingOperator`]. + /// Note that this should be only used when the operator is being freed + #[allow(clippy::mut_from_ref)] + pub(crate) fn get_ref_mut(&self) -> &mut od::BlockingOperator { + let ptr_mut = self.ptr as *mut od::BlockingOperator; + unsafe { &mut (*ptr_mut) } + } } #[allow(clippy::from_over_into)] @@ -91,7 +104,7 @@ impl Into for opendal_bytes { } } -/// Frees the heap memory used by the [`Bytes`] +/// Frees the heap memory used by the [`opendal_bytes`] #[no_mangle] pub extern "C" fn opendal_bytes_free(vec: *const opendal_bytes) { unsafe { diff --git a/bindings/c/tests/basicio.c b/bindings/c/tests/basicio.c index dc31ad2562f..aff1b49f8f3 100644 --- a/bindings/c/tests/basicio.c +++ b/bindings/c/tests/basicio.c @@ -21,6 +21,12 @@ #include "opendal.h" #include "stdio.h" +// Tests the basic IO operations work as expected +// +// Asserts: +// * A valid ptr is given +// * The blocking write operation is successful +// * The blocking read operation is successful and works as expected void test_operator_rw(opendal_operator_ptr ptr) { // have to be valid ptr assert(ptr); @@ -49,11 +55,15 @@ void test_operator_rw(opendal_operator_ptr ptr) { } int main(int argc, char *argv[]) { - // test memory operator + // construct the memory operator char scheme1[] = "memory"; opendal_operator_ptr p1 = opendal_operator_new(scheme1); assert(p1); + test_operator_rw(p1); + // free the operator + opendal_operator_free(p1); + return 0; }