diff --git a/bindings/c/README.md b/bindings/c/README.md index f4e58ad0dcc..398f1a1f198 100644 --- a/bindings/c/README.md +++ b/bindings/c/README.md @@ -43,7 +43,7 @@ int main() printf("\n"); /* the opendal_bytes read is heap allocated, please free it */ - opendal_bytes_free(read_bytes); + opendal_bytes_free(&read_bytes); /* the operator_ptr is also heap allocated */ opendal_operator_free(&op); diff --git a/bindings/c/examples/basic.c b/bindings/c/examples/basic.c index 5fde22d9c57..af55faeea0d 100644 --- a/bindings/c/examples/basic.c +++ b/bindings/c/examples/basic.c @@ -53,7 +53,7 @@ int main() printf("\n"); /* the opendal_bytes read is heap allocated, please free it */ - opendal_bytes_free(read_bytes); + opendal_bytes_free(&read_bytes); /* the operator_ptr is also heap allocated */ opendal_operator_free(op); diff --git a/bindings/c/include/opendal.h b/bindings/c/include/opendal.h index bc8b0f74ff1..882fb8b8e9a 100644 --- a/bindings/c/include/opendal.h +++ b/bindings/c/include/opendal.h @@ -844,7 +844,7 @@ struct opendal_error *opendal_operator_write(const struct opendal_operator *op, * * opendal_bytes bytes = r.data; * assert(bytes.len == 13); - * opendal_bytes_free(bytes); + * opendal_bytes_free(&bytes); * ``` * * # Safety @@ -1314,7 +1314,7 @@ struct opendal_capability opendal_operator_info_get_native_capability(const stru /** * \brief Frees the heap memory used by the opendal_bytes */ -void opendal_bytes_free(struct opendal_bytes bs); +void opendal_bytes_free(struct opendal_bytes *bs); /** * \brief Construct a heap-allocated opendal_operator_options diff --git a/bindings/c/src/operator.rs b/bindings/c/src/operator.rs index 99f20d612f3..ba03f9c2ae9 100644 --- a/bindings/c/src/operator.rs +++ b/bindings/c/src/operator.rs @@ -265,7 +265,7 @@ pub unsafe extern "C" fn opendal_operator_write( /// /// opendal_bytes bytes = r.data; /// assert(bytes.len == 13); -/// opendal_bytes_free(bytes); +/// opendal_bytes_free(&bytes); /// ``` /// /// # Safety diff --git a/bindings/c/src/types.rs b/bindings/c/src/types.rs index 045dbdec782..dcce095706d 100644 --- a/bindings/c/src/types.rs +++ b/bindings/c/src/types.rs @@ -59,21 +59,24 @@ impl opendal_bytes { /// \brief Frees the heap memory used by the opendal_bytes #[no_mangle] - pub unsafe extern "C" fn opendal_bytes_free(bs: opendal_bytes) { - drop(bs); + pub unsafe extern "C" fn opendal_bytes_free(bs: *mut opendal_bytes) { + if !bs.is_null() { + let bs = &mut *bs; + if !bs.data.is_null() { + drop(Vec::from_raw_parts(bs.data, bs.len, bs.capacity)); + bs.data = std::ptr::null_mut(); + bs.len = 0; + bs.capacity = 0; + } + } } } impl Drop for opendal_bytes { fn drop(&mut self) { - if !self.data.is_null() { - unsafe { - // Safety: the data is not null, and the capacity is correct - drop(Vec::from_raw_parts(self.data, self.len, self.capacity)); - } - self.data = std::ptr::null_mut(); - self.len = 0; - self.capacity = 0; + unsafe { + // Safety: the pointer is always valid + Self::opendal_bytes_free(self); } } } diff --git a/bindings/c/tests/bdd.cpp b/bindings/c/tests/bdd.cpp index 1aa37f5b3e0..65e97f52bf4 100644 --- a/bindings/c/tests/bdd.cpp +++ b/bindings/c/tests/bdd.cpp @@ -120,7 +120,7 @@ TEST_F(OpendalBddTest, FeatureTest) error = opendal_operator_delete(this->p, this->path.c_str()); EXPECT_EQ(error, nullptr); - opendal_bytes_free(r.data); + opendal_bytes_free(&r.data); // The directory "tmpdir/" should exist and should be a directory error = opendal_operator_create_dir(this->p, "tmpdir/"); diff --git a/bindings/c/tests/error_msg.cpp b/bindings/c/tests/error_msg.cpp index f2087ea3b0b..516d27865aa 100644 --- a/bindings/c/tests/error_msg.cpp +++ b/bindings/c/tests/error_msg.cpp @@ -59,7 +59,7 @@ TEST_F(OpendalErrorTest, ErrorReadTest) ASSERT_GT(error_msg->len, 0); // the opendal_bytes read is heap allocated, please free it - opendal_bytes_free(r.data); + opendal_bytes_free(&r.data); // free the error opendal_error_free(r.error); diff --git a/bindings/go/operator.go b/bindings/go/operator.go index 807bcc6908f..d63bacda61e 100644 --- a/bindings/go/operator.go +++ b/bindings/go/operator.go @@ -285,7 +285,7 @@ type bytesFree func(b *opendalBytes) var withBytesFree = withFFI(ffiOpts{ sym: symBytesFree, rType: &ffi.TypeVoid, - aTypes: []*ffi.Type{&typeBytes}, + aTypes: []*ffi.Type{&ffi.TypePointer}, }, func(_ context.Context, ffiCall func(rValue unsafe.Pointer, aValues ...unsafe.Pointer)) bytesFree { return func(b *opendalBytes) { ffiCall( diff --git a/bindings/swift/OpenDAL/Sources/OpenDAL/Data+OpenDAL.swift b/bindings/swift/OpenDAL/Sources/OpenDAL/Data+OpenDAL.swift index 41cdef22edd..8e619337546 100644 --- a/bindings/swift/OpenDAL/Sources/OpenDAL/Data+OpenDAL.swift +++ b/bindings/swift/OpenDAL/Sources/OpenDAL/Data+OpenDAL.swift @@ -25,9 +25,9 @@ extension Data { /// This can be used to read data from Rust with zero-copying. /// The underlying buffer will be freed when the data gets /// deallocated. - init(openDALBytes: opendal_bytes) { - let address = UnsafeRawPointer(openDALBytes.data)! - let length = Int(openDALBytes.len) + init(openDALBytes: UnsafeMutablePointer) { + let address = UnsafeRawPointer(openDALBytes.pointee.data)! + let length = Int(openDALBytes.pointee.len) self.init( bytesNoCopy: .init(mutating: address), count: length, diff --git a/bindings/swift/OpenDAL/Sources/OpenDAL/Operator.swift b/bindings/swift/OpenDAL/Sources/OpenDAL/Operator.swift index 00e28eb03c7..6e2bb3a7bd1 100644 --- a/bindings/swift/OpenDAL/Sources/OpenDAL/Operator.swift +++ b/bindings/swift/OpenDAL/Sources/OpenDAL/Operator.swift @@ -81,7 +81,7 @@ public class Operator { } public func blockingRead(_ path: String) throws -> Data { - let ret = opendal_operator_read(nativeOp, path) + var ret = opendal_operator_read(nativeOp, path) if let err = ret.error { defer { opendal_error_free(err) @@ -95,6 +95,6 @@ public class Operator { ) } - return Data(openDALBytes: ret.data) + return withUnsafeMutablePointer(to: &ret.data) { Data(openDALBytes: $0) } } } diff --git a/bindings/zig/test/bdd.zig b/bindings/zig/test/bdd.zig index 65f470d820c..042710f7db0 100644 --- a/bindings/zig/test/bdd.zig +++ b/bindings/zig/test/bdd.zig @@ -82,8 +82,8 @@ test "Opendal BDD test" { defer opendal.c.opendal_metadata_free(meta); // The blocking file "test" must have content "Hello, World!" - const r: opendal.c.opendal_result_read = opendal.c.opendal_operator_read(testkit.p, testkit.path); - defer opendal.c.opendal_bytes_free(r.data); + var r: opendal.c.opendal_result_read = opendal.c.opendal_operator_read(testkit.p, testkit.path); + defer opendal.c.opendal_bytes_free(&r.data); try testing.expect(r.@"error" == null); try testing.expectEqual(std.mem.len(testkit.content), r.data.len);