Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions bindings/c/include/opendal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1375,7 +1375,7 @@ struct opendal_error *opendal_operator_check(const struct opendal_operator *op);
* assert(!strcmp(scheme, "memory"));
*
* /// free the heap memory
* free(scheme);
* opendal_string_free(scheme);
* opendal_operator_info_free(info);
* ```
*/
Expand All @@ -1389,22 +1389,22 @@ void opendal_operator_info_free(struct opendal_operator_info *ptr);
/**
* \brief Return the nul-terminated operator's scheme, i.e. service
*
* \note: The string is on heap, remember to free it
* \note: The string is on heap, free it with opendal_string_free()
*/
char *opendal_operator_info_get_scheme(const struct opendal_operator_info *self);

/**
* \brief Return the nul-terminated operator's working root path
*
* \note: The string is on heap, remember to free it
* \note: The string is on heap, free it with opendal_string_free()
*/
char *opendal_operator_info_get_root(const struct opendal_operator_info *self);

/**
* \brief Return the nul-terminated operator backend's name, could be empty if underlying backend has no
* namespace concept.
*
* \note: The string is on heap, remember to free it
* \note: The string is on heap, free it with opendal_string_free()
*/
char *opendal_operator_info_get_name(const struct opendal_operator_info *self);

Expand Down Expand Up @@ -1471,6 +1471,13 @@ uintptr_t opendal_presigned_request_headers_len(const struct opendal_presigned_r
*/
void opendal_presigned_request_free(struct opendal_presigned_request *req);

/**
* \brief Frees a heap-allocated string returned by OpenDAL C APIs.
*
* \note Only pass pointers returned from OpenDAL APIs that transfer string ownership.
*/
void opendal_string_free(char *ptr);

/**
* \brief Frees the heap memory used by the opendal_bytes
*/
Expand Down Expand Up @@ -1519,7 +1526,7 @@ void opendal_operator_options_free(struct opendal_operator_options *ptr);
*
* Path is relative to operator's root. Only valid in current operator.
*
* \note To free the string, you can directly call free()
* \note Free the returned string with opendal_string_free()
*/
char *opendal_entry_path(const struct opendal_entry *self);

Expand All @@ -1530,7 +1537,7 @@ char *opendal_entry_path(const struct opendal_entry *self);
* If this entry is a dir, `Name` MUST endswith `/`
* Otherwise, `Name` MUST NOT endswith `/`.
*
* \note To free the string, you can directly call free()
* \note Free the returned string with opendal_string_free()
*/
char *opendal_entry_name(const struct opendal_entry *self);

Expand Down
4 changes: 2 additions & 2 deletions bindings/c/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl opendal_entry {
///
/// Path is relative to operator's root. Only valid in current operator.
///
/// \note To free the string, you can directly call free()
/// \note Free the returned string with opendal_string_free()
#[no_mangle]
pub unsafe extern "C" fn opendal_entry_path(&self) -> *mut c_char {
let s = self.deref().path();
Expand All @@ -67,7 +67,7 @@ impl opendal_entry {
/// If this entry is a dir, `Name` MUST endswith `/`
/// Otherwise, `Name` MUST NOT endswith `/`.
///
/// \note To free the string, you can directly call free()
/// \note Free the returned string with opendal_string_free()
#[no_mangle]
pub unsafe extern "C" fn opendal_entry_name(&self) -> *mut c_char {
let s = self.deref().name();
Expand Down
8 changes: 4 additions & 4 deletions bindings/c/src/operator_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ impl opendal_operator_info {
/// assert(!strcmp(scheme, "memory"));
///
/// /// free the heap memory
/// free(scheme);
/// opendal_string_free(scheme);
/// opendal_operator_info_free(info);
/// ```
#[no_mangle]
Expand All @@ -170,7 +170,7 @@ impl opendal_operator_info {

/// \brief Return the nul-terminated operator's scheme, i.e. service
///
/// \note: The string is on heap, remember to free it
/// \note: The string is on heap, free it with opendal_string_free()
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_info_get_scheme(&self) -> *mut c_char {
let scheme = self.deref().scheme().to_string();
Expand All @@ -181,7 +181,7 @@ impl opendal_operator_info {

/// \brief Return the nul-terminated operator's working root path
///
/// \note: The string is on heap, remember to free it
/// \note: The string is on heap, free it with opendal_string_free()
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_info_get_root(&self) -> *mut c_char {
let root = self.deref().root();
Expand All @@ -193,7 +193,7 @@ impl opendal_operator_info {
/// \brief Return the nul-terminated operator backend's name, could be empty if underlying backend has no
/// namespace concept.
///
/// \note: The string is on heap, remember to free it
/// \note: The string is on heap, free it with opendal_string_free()
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_info_get_name(&self) -> *mut c_char {
let name = self.deref().name();
Expand Down
12 changes: 11 additions & 1 deletion bindings/c/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,21 @@
// under the License.

use std::collections::HashMap;
use std::ffi::c_void;
use std::ffi::{c_void, CString};
use std::os::raw::c_char;

use opendal::Buffer;

/// \brief Frees a heap-allocated string returned by OpenDAL C APIs.
///
/// \note Only pass pointers returned from OpenDAL APIs that transfer string ownership.
#[no_mangle]
pub unsafe extern "C" fn opendal_string_free(ptr: *mut c_char) {
if !ptr.is_null() {
drop(unsafe { CString::from_raw(ptr) });
}
}

/// \brief opendal_bytes carries raw-bytes with its length
///
/// The opendal_bytes type is a C-compatible substitute for Vec type
Expand Down
2 changes: 1 addition & 1 deletion bindings/c/tests/list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ TEST_F(OpendalListTest, ListDirTest)
EXPECT_EQ(opendal_metadata_content_length(s.meta), nbytes);
}

free(de_path);
opendal_string_free(de_path);
opendal_metadata_free(s.meta);
opendal_entry_free(entry);

Expand Down
4 changes: 2 additions & 2 deletions bindings/c/tests/opinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,6 @@ TEST_F(OpendalOperatorInfoTest, InfoTest)
EXPECT_TRUE(!strcmp(root, this->root.c_str()));

// remember to free the strings
free(scheme);
free(root);
opendal_string_free(scheme);
opendal_string_free(root);
}
10 changes: 5 additions & 5 deletions bindings/c/tests/test_suites_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ void test_list_basic(opendal_test_context* ctx)
OPENDAL_ASSERT_NOT_NULL(path, "Entry path should not be null");
found_paths.insert(std::string(path));

free(path);
opendal_string_free(path);
opendal_entry_free(next_result.entry);
}

Expand Down Expand Up @@ -124,7 +124,7 @@ void test_list_empty_dir(opendal_test_context* ctx)

char* path = opendal_entry_path(next_result.entry);
found_paths.insert(std::string(path));
free(path);
opendal_string_free(path);
opendal_entry_free(next_result.entry);
}

Expand Down Expand Up @@ -191,7 +191,7 @@ void test_list_nested(opendal_test_context* ctx)

char* path = opendal_entry_path(next_result.entry);
found_paths.insert(std::string(path));
free(path);
opendal_string_free(path);
opendal_entry_free(next_result.entry);
}

Expand Down Expand Up @@ -269,8 +269,8 @@ void test_entry_name_path(opendal_test_context* ctx)
"Entry path should be the full path");
}

free(path);
free(name);
opendal_string_free(path);
opendal_string_free(name);
opendal_entry_free(next_result.entry);
}

Expand Down
62 changes: 34 additions & 28 deletions bindings/go/lister.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,32 +366,38 @@ var ffiEntryFree = newFFI(ffiOpts{
}
})

var ffiEntryName = newFFI(ffiOpts{
sym: "opendal_entry_name",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
}, func(ctx context.Context, ffiCall ffiCall) func(e *opendalEntry) string {
return func(e *opendalEntry) string {
var bytePtr *byte
ffiCall(
unsafe.Pointer(&bytePtr),
unsafe.Pointer(&e),
)
return BytePtrToString(bytePtr)
}
})
var ffiEntryName = func() *FFI[func(e *opendalEntry) string] {
_ = ffiStringFree
return newFFI(ffiOpts{
sym: "opendal_entry_name",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
}, func(ctx context.Context, ffiCall ffiCall) func(e *opendalEntry) string {
return func(e *opendalEntry) string {
var bytePtr *byte
ffiCall(
unsafe.Pointer(&bytePtr),
unsafe.Pointer(&e),
)
return copyCStringAndFree(bytePtr, ffiStringFree.symbol(ctx))
}
})
}()

var ffiEntryPath = newFFI(ffiOpts{
sym: "opendal_entry_path",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
}, func(ctx context.Context, ffiCall ffiCall) func(e *opendalEntry) string {
return func(e *opendalEntry) string {
var bytePtr *byte
ffiCall(
unsafe.Pointer(&bytePtr),
unsafe.Pointer(&e),
)
return BytePtrToString(bytePtr)
}
})
var ffiEntryPath = func() *FFI[func(e *opendalEntry) string] {
_ = ffiStringFree
return newFFI(ffiOpts{
sym: "opendal_entry_path",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
}, func(ctx context.Context, ffiCall ffiCall) func(e *opendalEntry) string {
return func(e *opendalEntry) string {
var bytePtr *byte
ffiCall(
unsafe.Pointer(&bytePtr),
unsafe.Pointer(&e),
)
return copyCStringAndFree(bytePtr, ffiStringFree.symbol(ctx))
}
})
}()
97 changes: 53 additions & 44 deletions bindings/go/operator_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,47 +289,56 @@ var ffiOperatorInfoGetNativeCapability = newFFI(ffiOpts{
}
})

var ffiOperatorInfoGetScheme = newFFI(ffiOpts{
sym: "opendal_operator_info_get_scheme",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
}, func(ctx context.Context, ffiCall ffiCall) func(info *opendalOperatorInfo) string {
return func(info *opendalOperatorInfo) string {
var bytePtr *byte
ffiCall(
unsafe.Pointer(&bytePtr),
unsafe.Pointer(&info),
)
return BytePtrToString(bytePtr)
}
})

var ffiOperatorInfoGetRoot = newFFI(ffiOpts{
sym: "opendal_operator_info_get_root",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
}, func(ctx context.Context, ffiCall ffiCall) func(info *opendalOperatorInfo) string {
return func(info *opendalOperatorInfo) string {
var bytePtr *byte
ffiCall(
unsafe.Pointer(&bytePtr),
unsafe.Pointer(&info),
)
return BytePtrToString(bytePtr)
}
})

var ffiOperatorInfoGetName = newFFI(ffiOpts{
sym: "opendal_operator_info_get_name",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
}, func(ctx context.Context, ffiCall ffiCall) func(info *opendalOperatorInfo) string {
return func(info *opendalOperatorInfo) string {
var bytePtr *byte
ffiCall(
unsafe.Pointer(&bytePtr),
unsafe.Pointer(&info),
)
return BytePtrToString(bytePtr)
}
})
var ffiOperatorInfoGetScheme = func() *FFI[func(info *opendalOperatorInfo) string] {
_ = ffiStringFree
return newFFI(ffiOpts{
sym: "opendal_operator_info_get_scheme",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
}, func(ctx context.Context, ffiCall ffiCall) func(info *opendalOperatorInfo) string {
return func(info *opendalOperatorInfo) string {
var bytePtr *byte
ffiCall(
unsafe.Pointer(&bytePtr),
unsafe.Pointer(&info),
)
return copyCStringAndFree(bytePtr, ffiStringFree.symbol(ctx))
}
})
}()

var ffiOperatorInfoGetRoot = func() *FFI[func(info *opendalOperatorInfo) string] {
_ = ffiStringFree
return newFFI(ffiOpts{
sym: "opendal_operator_info_get_root",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
}, func(ctx context.Context, ffiCall ffiCall) func(info *opendalOperatorInfo) string {
return func(info *opendalOperatorInfo) string {
var bytePtr *byte
ffiCall(
unsafe.Pointer(&bytePtr),
unsafe.Pointer(&info),
)
return copyCStringAndFree(bytePtr, ffiStringFree.symbol(ctx))
}
})
}()

var ffiOperatorInfoGetName = func() *FFI[func(info *opendalOperatorInfo) string] {
_ = ffiStringFree
return newFFI(ffiOpts{
sym: "opendal_operator_info_get_name",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
}, func(ctx context.Context, ffiCall ffiCall) func(info *opendalOperatorInfo) string {
return func(info *opendalOperatorInfo) string {
var bytePtr *byte
ffiCall(
unsafe.Pointer(&bytePtr),
unsafe.Pointer(&info),
)
return copyCStringAndFree(bytePtr, ffiStringFree.symbol(ctx))
}
})
}()
Loading
Loading