This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal.git
The following commit(s) were added to refs/heads/main by this push:
new ff2a6467b refactor(bindings/go): Restructure FFI system with type-safe
wrapper (#6268)
ff2a6467b is described below
commit ff2a6467b90a52e951ffdff74592d39d5f685020
Author: Hanchin Hsieh <[email protected]>
AuthorDate: Tue Jun 10 22:36:26 2025 +0800
refactor(bindings/go): Restructure FFI system with type-safe wrapper (#6268)
---
bindings/go/Makefile | 118 +++++++++++++++++++++++++++++++
bindings/go/README.md | 67 ++----------------
bindings/go/delete.go | 13 ++--
bindings/go/error.go | 13 ++--
bindings/go/ffi.go | 160 +++++++++++++++----------------------------
bindings/go/lister.go | 79 +++++++--------------
bindings/go/metadata.go | 65 ++++++------------
bindings/go/opendal.go | 14 ++--
bindings/go/operator.go | 88 ++++++++----------------
bindings/go/operator_info.go | 92 ++++++++-----------------
bindings/go/reader.go | 67 ++++++------------
bindings/go/stat.go | 26 +++----
bindings/go/write.go | 87 ++++++++---------------
13 files changed, 349 insertions(+), 540 deletions(-)
diff --git a/bindings/go/Makefile b/bindings/go/Makefile
new file mode 100644
index 000000000..861b42661
--- /dev/null
+++ b/bindings/go/Makefile
@@ -0,0 +1,118 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+.PHONY: tests clean help check-env generate-services run-tests
+
+# Detect current OS and architecture
+OS := $(shell uname -s | tr '[:upper:]' '[:lower:]')
+ARCH := $(shell uname -m)
+
+# Normalize architecture names
+ifeq ($(ARCH),x86_64)
+ ARCH := amd64
+endif
+ifeq ($(ARCH),aarch64)
+ ARCH := arm64
+endif
+
+# Define file extensions for different OS
+ifeq ($(OS),linux)
+ LIB_EXT := so
+endif
+ifeq ($(OS),darwin)
+ LIB_EXT := dylib
+endif
+ifeq ($(findstring mingw,$(OS)),mingw)
+ OS := windows
+ LIB_EXT := dll
+endif
+ifeq ($(findstring msys,$(OS)),msys)
+ OS := windows
+ LIB_EXT := dll
+endif
+
+# Check if OPENDAL_TEST environment variable is set
+check-env:
+ @if [ -z "$(OPENDAL_TEST)" ]; then \
+ echo "Error: OPENDAL_TEST environment variable is not set"; \
+ echo "Please set OPENDAL_TEST to the service you want to test
(e.g., fs, s3, etc.)"; \
+ exit 1; \
+ fi
+
+# Other variables
+SERVICE := $(OPENDAL_TEST)
+GITHUB_WORKSPACE := $(PWD)/opendal-go-services
+VERSION := latest
+MATRIX := '{"build": [{"target":"$(OS)", "goos":"$(OS)", "goarch":
"$(ARCH)"}], "service": ["$(SERVICE)"]}'
+
+# Define library file paths
+C_LIB_FILE := opendal/bindings/c/target/debug/libopendal_c.$(LIB_EXT)
+SERVICE_PKG := $(shell echo $(SERVICE) | tr '-' '_')
+FINAL_LIB_FILE :=
$(GITHUB_WORKSPACE)/$(SERVICE_PKG)/libopendal_c.$(OS).$(ARCH).$(LIB_EXT).zst
+
+# Build C library only when source files change
+$(C_LIB_FILE): opendal/bindings/c/src/*.rs opendal/bindings/c/Cargo.toml
+ @echo "Building C library for service: $(SERVICE)"
+ cd opendal/bindings/c && cargo build --features
"opendal/services-$(SERVICE)"
+
+# Create compressed library and generate services in one step
+# This target depends on the final library file location, not intermediate
+$(FINAL_LIB_FILE): $(C_LIB_FILE)
+ @echo "Compressing library and generating services for $(SERVICE) on
$(OS)..."
+ @mkdir -p $(GITHUB_WORKSPACE)/libopendal_c_$(VERSION)_$(SERVICE)_$(OS)
+ zstd -19 $< -o
$(GITHUB_WORKSPACE)/libopendal_c_$(VERSION)_$(SERVICE)_$(OS)/libopendal_c.$(OS).$(LIB_EXT).zst
+ @echo "Generating Go services..."
+ cd opendal-go-services/internal/generate && \
+ GITHUB_WORKSPACE="$(GITHUB_WORKSPACE)" \
+ VERSION="$(VERSION)" \
+ MATRIX=$(MATRIX) \
+ go run generate.go
+ @echo "Cleaning up intermediate directory..."
+ @rm -rf $(GITHUB_WORKSPACE)/libopendal_c_$(VERSION)_$(SERVICE)_$(OS)
+
+# Generate services target now just depends on the final file
+generate-services: $(FINAL_LIB_FILE)
+
+# Run tests
+run-tests: generate-services
+ @echo "Running behavior tests..."
+ go test ./opendal/bindings/go/tests/behavior_tests -v -run TestBehavior
+
+# Main target: run all tests
+tests: check-env run-tests
+ @echo "All tests completed successfully!"
+
+# Clean all generated files
+clean:
+ @echo "Cleaning all generated files..."
+ rm -rf opendal/bindings/c/target
+ rm -rf opendal-go-services/*/libopendal_c.*
+ rm -rf opendal-go-services/libopendal_c_*
+
+# Help target
+help:
+ @echo "Available targets:"
+ @echo " tests - Run all tests (requires OPENDAL_TEST
environment variable)"
+ @echo " clean - Clean all generated files"
+ @echo " help - Show this help message"
+ @echo ""
+ @echo "Environment variables:"
+ @echo " OPENDAL_TEST - Required. The service to test (e.g., fs, s3,
gcs, etc.)"
+ @echo ""
+ @echo "Example usage:"
+ @echo " OPENDAL_TEST=fs make tests"
+
diff --git a/bindings/go/README.md b/bindings/go/README.md
index bc00d4246..265c9b170 100644
--- a/bindings/go/README.md
+++ b/bindings/go/README.md
@@ -222,7 +222,7 @@ We use `go workspace` to manage and build the dependencies.
To set up the worksp
<details>
<summary>
- For Linux
+ For Linux and macOS
</summary>
<br/>
@@ -240,65 +240,7 @@ go work use ./opendal/bindings/go/tests/behavior_tests
go work use ./opendal-go-services/fs
go work use ./opendal-go-services/memory
-cat <<EOF > ./make_test.sh
-#!/bin/bash
-
-# Check if OPENDAL_TEST is set
-if [ -z "\$OPENDAL_TEST" ]; then
- echo "Error: OPENDAL_TEST environment variable is not set"
- echo "Please set OPENDAL_TEST to specify which backend to test (e.g., fs
or memory)"
- exit 1
-fi
-
-# Specify the backend to test
-export SERVICE="\$OPENDAL_TEST"
-
-# Get architecture
-architecture=\$(uname -m)
-if [ "\$architecture" = "x86_64" ]; then
- ARCH="amd64"
- GOARCH="amd64"
-elif [ "\$architecture" = "aarch64" ] || [ "\$architecture" = "arm64" ]; then
- ARCH="arm64"
- GOARCH="arm64"
-else
- ARCH="unknown"
-fi
-
-# Build opendal
-cd opendal/bindings/c
-cargo build
-cd -
-
-# Set environment variables
-export GITHUB_WORKSPACE="\$PWD/opendal-go-services"
-export VERSION="latest"
-export TARGET="linux"
-export DIR="\$GITHUB_WORKSPACE/libopendal_c_\${VERSION}_\${SERVICE}_\${TARGET}"
-
-# Create directory if not exists
-mkdir -p "\$DIR"
-
-export OUTPUT="\$DIR/libopendal_c.\$TARGET.so.zst"
-# Compress with zstd
-zstd -19 opendal/bindings/c/target/debug/libopendal_c.so -o \$OUTPUT
-
-# Set environment variables for test
-export MATRIX='{"build": [{"target":"linux", "goos":"linux", "goarch":
"'\$GOARCH'"}], "service": ["fs"]}'
-
-# Generate code
-cd opendal-go-services/internal/generate
-go run generate.go
-cd -
-
-# Delete unnecessary files
-rm -rf \$DIR
-
-# Run tests
-go test ./opendal/bindings/go/tests/behavior_tests -v -run TestBehavior
-EOF
-
-chmod +x ./make_test.sh
+cp opendal/bindings/go/Makefile .
cd -
```
@@ -312,8 +254,7 @@ cd opendal_workspace
export OPENDAL_TEST=fs
export OPENDAL_FS_ROOT=/tmp/opendal
-# build the C binding and run the tests
-./make_test.sh
+make tests
cd -
```
@@ -342,7 +283,7 @@ go work use ./opendal-go-services/fs
go work use ./opendal-go-services/memory
@'
-# Check if OPENDAL_TEST is set\;if (-not $env:OPENDAL_TEST) {\; Write-Error
"OPENDAL_TEST environment variable is not set"\; Write-Host "Please set
OPENDAL_TEST to specify which backend to test (e.g., fs or memory)"\; exit
1\;}\;# Specify the backend to test\;Set-Item -Path Env:SERVICE -Value
"$env:OPENDAL_TEST"\;# Get architecture\;$architecture = (Get-WmiObject
Win32_OperatingSystem).OSArchitecture\;\;if ($architecture -like "*64*") {\;
$ARCH = "x86_64"\;} else {\; $ARCH [...]
+# Check if OPENDAL_TEST is set\;if (-not $env:OPENDAL_TEST) {\; Write-Error
"OPENDAL_TEST environment variable is not set"\; Write-Host "Please set
OPENDAL_TEST to specify which backend to test (e.g., fs or memory)"\; exit
1\;}\;# Specify the backend to test\;Set-Item -Path Env:SERVICE -Value
"$env:OPENDAL_TEST"\;# Get architecture\;$architecture = (Get-WmiObject
Win32_OperatingSystem).OSArchitecture\;\;if ($architecture -like "*64*") {\;
$ARCH = "x86_64"\;} else {\; $ARCH [...]
'@ -replace "\\;","`n" | Out-File -FilePath "MakeTest.ps1" -Encoding UTF8
Pop-Location
diff --git a/bindings/go/delete.go b/bindings/go/delete.go
index 31903383c..f7fd9b6f0 100644
--- a/bindings/go/delete.go
+++ b/bindings/go/delete.go
@@ -40,19 +40,14 @@ import (
//
// Use with caution as this operation is irreversible.
func (op *Operator) Delete(path string) error {
- delete := getFFI[operatorDelete](op.ctx, symOperatorDelete)
- return delete(op.inner, path)
+ return ffiOperatorDelete.symbol(op.ctx)(op.inner, path)
}
-type operatorDelete func(op *opendalOperator, path string) error
-
-const symOperatorDelete = "opendal_operator_delete"
-
-var withOperatorDelete = withFFI(ffiOpts{
- sym: symOperatorDelete,
+var ffiOperatorDelete = newFFI(ffiOpts{
+ sym: "opendal_operator_delete",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorDelete {
+}, func(ctx context.Context, ffiCall ffiCall) func(op *opendalOperator, path
string) error {
return func(op *opendalOperator, path string) error {
bytePath, err := BytePtrFromString(path)
if err != nil {
diff --git a/bindings/go/error.go b/bindings/go/error.go
index 9e7c2de9c..899f75661 100644
--- a/bindings/go/error.go
+++ b/bindings/go/error.go
@@ -73,8 +73,7 @@ func parseError(ctx context.Context, err *opendalError) error
{
if err == nil {
return nil
}
- free := getFFI[errorFree](ctx, symErrorFree)
- defer free(err)
+ defer ffiErrorFree.symbol(ctx)(err)
return &Error{
code: ErrorCode(err.code),
message: string(parseBytes(err.message)),
@@ -98,15 +97,11 @@ func (e *Error) Message() string {
return e.message
}
-type errorFree func(e *opendalError)
-
-const symErrorFree = "opendal_error_free"
-
-var withErrorFree = withFFI(ffiOpts{
- sym: symErrorFree,
+var ffiErrorFree = newFFI(ffiOpts{
+ sym: "opendal_error_free",
rType: &ffi.TypeVoid,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(_ context.Context, ffiCall ffiCall) errorFree {
+}, func(_ context.Context, ffiCall ffiCall) func(e *opendalError) {
return func(e *opendalError) {
ffiCall(
nil,
diff --git a/bindings/go/ffi.go b/bindings/go/ffi.go
index df1e6e3f2..376663600 100644
--- a/bindings/go/ffi.go
+++ b/bindings/go/ffi.go
@@ -27,37 +27,6 @@ import (
"github.com/jupiterrider/ffi"
)
-func contextWithFFIs(path string) (ctx context.Context, cancel
context.CancelFunc, err error) {
- libopendal, err := LoadLibrary(path)
- if err != nil {
- return
- }
- ctx = context.Background()
- for _, withFFI := range withFFIs {
- ctx, err = withFFI(ctx, libopendal)
- if err != nil {
- return
- }
- }
- cancel = func() {
- _ = FreeLibrary(libopendal)
- }
- return
-}
-
-type contextWithFFI func(ctx context.Context, libopendal uintptr)
(context.Context, error)
-
-func getFFI[T any](ctx context.Context, key string) T {
- ctxKey := contextKey(key)
- return ctx.Value(ctxKey).(T)
-}
-
-type contextKey string
-
-func (k contextKey) String() string {
- return string(k)
-}
-
type ffiOpts struct {
sym contextKey
rType *ffi.Type
@@ -66,85 +35,70 @@ type ffiOpts struct {
type ffiCall func(rValue unsafe.Pointer, aValues ...unsafe.Pointer)
-func withFFI[T any](
- opts ffiOpts,
- withFunc func(
- ctx context.Context,
- ffiCall ffiCall,
- ) T,
-) func(ctx context.Context, libopendal uintptr) (context.Context, error) {
- return func(ctx context.Context, libopendal uintptr) (context.Context,
error) {
- var cif ffi.Cif
- if status := ffi.PrepCif(
- &cif,
- ffi.DefaultAbi,
- uint32(len(opts.aTypes)),
- opts.rType,
- opts.aTypes...,
- ); status != ffi.OK {
- return nil, errors.New(status.String())
- }
- fn, err := GetProcAddress(libopendal, opts.sym.String())
- if err != nil {
- return nil, err
- }
- return context.WithValue(ctx, opts.sym,
- withFunc(ctx, func(rValue unsafe.Pointer, aValues
...unsafe.Pointer) {
- ffi.Call(&cif, fn, rValue, aValues...)
- }),
- ), nil
- }
-}
+type contextKey string
-var withFFIs = []contextWithFFI{
- // free must be on top
- withBytesFree,
- withErrorFree,
+func (c contextKey) String() string {
+ return string(c)
+}
- withOperatorOptionsNew,
- withOperatorOptionsSet,
- withOperatorOptionsFree,
+type contextWithFFI func(ctx context.Context, lib uintptr) (context.Context,
error)
- withOperatorNew,
- withOperatorFree,
+type FFI[T any] struct {
+ opts ffiOpts
+ withFunc func(ctx context.Context, ffiCall ffiCall) T
+}
- withOperatorInfoNew,
- withOperatorInfoGetFullCapability,
- withOperatorInfoGetNativeCapability,
- withOperatorInfoGetScheme,
- withOperatorInfoGetRoot,
- withOperatorInfoGetName,
- withOperatorInfoFree,
+func newFFI[T any](opts ffiOpts, withFunc func(ctx context.Context, ffiCall
ffiCall) T) *FFI[T] {
+ ffi := &FFI[T]{
+ opts: opts,
+ withFunc: withFunc,
+ }
+ withFFIs = append(withFFIs, ffi.withFFI)
+ return ffi
+}
- withOperatorCreateDir,
- withOperatorRead,
- withOperatorWrite,
- withOperatorDelete,
- withOperatorStat,
- withOperatorIsExists,
- withOperatorCopy,
- withOperatorRename,
+func (f *FFI[T]) symbol(ctx context.Context) T {
+ return ctx.Value(f.opts.sym).(T)
+}
- withMetaContentLength,
- withMetaIsFile,
- withMetaIsDir,
- withMetaLastModified,
- withMetaFree,
+func (f *FFI[T]) withFFI(ctx context.Context, lib uintptr) (context.Context,
error) {
+ var cif ffi.Cif
+ if status := ffi.PrepCif(
+ &cif,
+ ffi.DefaultAbi,
+ uint32(len(f.opts.aTypes)),
+ f.opts.rType,
+ f.opts.aTypes...,
+ ); status != ffi.OK {
+ return nil, errors.New(status.String())
+ }
+ fn, err := GetProcAddress(lib, f.opts.sym.String())
+ if err != nil {
+ return nil, err
+ }
+ val := f.withFunc(ctx, func(rValue unsafe.Pointer, aValues
...unsafe.Pointer) {
+ ffi.Call(&cif, fn, rValue, aValues...)
+ })
+ return context.WithValue(ctx, f.opts.sym, val), nil
+}
- withOperatorList,
- withListerNext,
- withListerFree,
- withEntryName,
- withEntryPath,
- withEntryFree,
+var withFFIs []contextWithFFI
- withOperatorReader,
- withReaderRead,
- withReaderSeek,
- withReaderFree,
+func newContext(path string) (ctx context.Context, cancel context.CancelFunc,
err error) {
+ lib, err := LoadLibrary(path)
+ if err != nil {
+ return
+ }
+ ctx = context.Background()
+ for _, withFFI := range withFFIs {
+ ctx, err = withFFI(ctx, lib)
+ if err != nil {
+ return
+ }
+ }
+ cancel = func() {
+ _ = FreeLibrary(lib)
+ }
- withOperatorWriter,
- withWriterWrite,
- withWriterFree,
- withWriterClose,
+ return
}
diff --git a/bindings/go/lister.go b/bindings/go/lister.go
index 5ec7de0d5..0d24fbc77 100644
--- a/bindings/go/lister.go
+++ b/bindings/go/lister.go
@@ -121,8 +121,7 @@ func (op *Operator) Check() (err error) {
// Note: Always check lister.Err() after the loop to catch any errors that
// occurred during iteration.
func (op *Operator) List(path string) (*Lister, error) {
- list := getFFI[operatorList](op.ctx, symOperatorList)
- inner, err := list(op.inner, path)
+ inner, err := ffiOperatorList.symbol(op.ctx)(op.inner, path)
if err != nil {
return nil, err
}
@@ -175,8 +174,7 @@ type Lister struct {
// This method implements the io.Closer interface. It should be called when
// the Lister is no longer needed to ensure proper resource cleanup.
func (l *Lister) Close() error {
- free := getFFI[listerFree](l.ctx, symListerFree)
- free(l.inner)
+ ffiListerFree.symbol(l.ctx)(l.inner)
return nil
}
@@ -222,8 +220,7 @@ func (l *Lister) Error() error {
// fmt.Println(entry.Name())
// }
func (l *Lister) Next() bool {
- next := getFFI[listerNext](l.ctx, symListerNext)
- inner, err := next(l.inner)
+ inner, err := ffiListerNext.symbol(l.ctx)(l.inner)
if inner == nil || err != nil {
l.err = err
l.entry = nil
@@ -284,15 +281,11 @@ type Entry struct {
}
func newEntry(ctx context.Context, inner *opendalEntry) *Entry {
- name := getFFI[entryName](ctx, symEntryName)
- path := getFFI[entryPath](ctx, symEntryPath)
- free := getFFI[entryFree](ctx, symEntryFree)
-
- defer free(inner)
+ defer ffiEntryFree.symbol(ctx)(inner)
return &Entry{
- name: name(inner),
- path: path(inner),
+ name: ffiEntryName.symbol(ctx)(inner),
+ path: ffiEntryPath.symbol(ctx)(inner),
}
}
@@ -306,15 +299,11 @@ func (e *Entry) Path() string {
return e.path
}
-const symOperatorList = "opendal_operator_list"
-
-type operatorList func(op *opendalOperator, path string) (*opendalLister,
error)
-
-var withOperatorList = withFFI(ffiOpts{
- sym: symOperatorList,
+var ffiOperatorList = newFFI(ffiOpts{
+ sym: "opendal_operator_list",
rType: &typeResultList,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorList {
+}, func(ctx context.Context, ffiCall ffiCall) func(op *opendalOperator, path
string) (*opendalLister, error) {
return func(op *opendalOperator, path string) (*opendalLister, error) {
bytePath, err := BytePtrFromString(path)
if err != nil {
@@ -333,15 +322,11 @@ var withOperatorList = withFFI(ffiOpts{
}
})
-const symListerFree = "opendal_lister_free"
-
-type listerFree func(l *opendalLister)
-
-var withListerFree = withFFI(ffiOpts{
- sym: symListerFree,
+var ffiListerFree = newFFI(ffiOpts{
+ sym: "opendal_lister_free",
rType: &ffi.TypeVoid,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) listerFree {
+}, func(ctx context.Context, ffiCall ffiCall) func(l *opendalLister) {
return func(l *opendalLister) {
ffiCall(
nil,
@@ -350,15 +335,11 @@ var withListerFree = withFFI(ffiOpts{
}
})
-const symListerNext = "opendal_lister_next"
-
-type listerNext func(l *opendalLister) (*opendalEntry, error)
-
-var withListerNext = withFFI(ffiOpts{
- sym: symListerNext,
+var ffiListerNext = newFFI(ffiOpts{
+ sym: "opendal_lister_next",
rType: &typeResultListerNext,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) listerNext {
+}, func(ctx context.Context, ffiCall ffiCall) func(l *opendalLister)
(*opendalEntry, error) {
return func(l *opendalLister) (*opendalEntry, error) {
var result opendalResultListerNext
ffiCall(
@@ -372,15 +353,11 @@ var withListerNext = withFFI(ffiOpts{
}
})
-const symEntryFree = "opendal_entry_free"
-
-type entryFree func(e *opendalEntry)
-
-var withEntryFree = withFFI(ffiOpts{
- sym: symEntryFree,
+var ffiEntryFree = newFFI(ffiOpts{
+ sym: "opendal_entry_free",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) entryFree {
+}, func(ctx context.Context, ffiCall ffiCall) func(e *opendalEntry) {
return func(e *opendalEntry) {
ffiCall(
nil,
@@ -389,15 +366,11 @@ var withEntryFree = withFFI(ffiOpts{
}
})
-const symEntryName = "opendal_entry_name"
-
-type entryName func(e *opendalEntry) string
-
-var withEntryName = withFFI(ffiOpts{
- sym: symEntryName,
+var ffiEntryName = newFFI(ffiOpts{
+ sym: "opendal_entry_name",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) entryName {
+}, func(ctx context.Context, ffiCall ffiCall) func(e *opendalEntry) string {
return func(e *opendalEntry) string {
var bytePtr *byte
ffiCall(
@@ -408,15 +381,11 @@ var withEntryName = withFFI(ffiOpts{
}
})
-const symEntryPath = "opendal_entry_path"
-
-type entryPath func(e *opendalEntry) string
-
-var withEntryPath = withFFI(ffiOpts{
- sym: symEntryPath,
+var ffiEntryPath = newFFI(ffiOpts{
+ sym: "opendal_entry_path",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) entryPath {
+}, func(ctx context.Context, ffiCall ffiCall) func(e *opendalEntry) string {
return func(e *opendalEntry) string {
var bytePtr *byte
ffiCall(
diff --git a/bindings/go/metadata.go b/bindings/go/metadata.go
index ccdfebd0f..daff59d63 100644
--- a/bindings/go/metadata.go
+++ b/bindings/go/metadata.go
@@ -39,24 +39,19 @@ type Metadata struct {
}
func newMetadata(ctx context.Context, inner *opendalMetadata) *Metadata {
- getLength := getFFI[metaContentLength](ctx, symMetadataContentLength)
- isFile := getFFI[metaIsFile](ctx, symMetadataIsFile)
- isDir := getFFI[metaIsDir](ctx, symMetadataIsDir)
- getLastModified := getFFI[metaLastModified](ctx,
symMetadataLastModified)
var lastModified time.Time
- ms := getLastModified(inner)
+ ms := ffiMetaLastModified.symbol(ctx)(inner)
if ms != -1 {
lastModified = time.UnixMilli(ms)
}
- free := getFFI[metaFree](ctx, symMetadataFree)
- defer free(inner)
+ defer ffiMetadataFree.symbol(ctx)(inner)
return &Metadata{
- contentLength: getLength(inner),
- isFile: isFile(inner),
- isDir: isDir(inner),
+ contentLength: ffiMetaContentLength.symbol(ctx)(inner),
+ isFile: ffiMetaIsFile.symbol(ctx)(inner),
+ isDir: ffiMetaIsDir.symbol(ctx)(inner),
lastModified: lastModified,
}
}
@@ -85,15 +80,11 @@ func (m *Metadata) LastModified() time.Time {
return m.lastModified
}
-type metaContentLength func(m *opendalMetadata) uint64
-
-const symMetadataContentLength = "opendal_metadata_content_length"
-
-var withMetaContentLength = withFFI(ffiOpts{
- sym: symMetadataContentLength,
+var ffiMetaContentLength = newFFI(ffiOpts{
+ sym: "opendal_metadata_content_length",
rType: &ffi.TypeUint64,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) metaContentLength {
+}, func(ctx context.Context, ffiCall ffiCall) func(m *opendalMetadata) uint64 {
return func(m *opendalMetadata) uint64 {
var length uint64
ffiCall(
@@ -104,15 +95,11 @@ var withMetaContentLength = withFFI(ffiOpts{
}
})
-type metaIsFile func(m *opendalMetadata) bool
-
-const symMetadataIsFile = "opendal_metadata_is_file"
-
-var withMetaIsFile = withFFI(ffiOpts{
- sym: symMetadataIsFile,
+var ffiMetaIsFile = newFFI(ffiOpts{
+ sym: "opendal_metadata_is_file",
rType: &ffi.TypeUint8,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) metaIsFile {
+}, func(ctx context.Context, ffiCall ffiCall) func(m *opendalMetadata) bool {
return func(m *opendalMetadata) bool {
var result uint8
ffiCall(
@@ -123,15 +110,11 @@ var withMetaIsFile = withFFI(ffiOpts{
}
})
-type metaIsDir func(m *opendalMetadata) bool
-
-const symMetadataIsDir = "opendal_metadata_is_dir"
-
-var withMetaIsDir = withFFI(ffiOpts{
- sym: symMetadataIsDir,
+var ffiMetaIsDir = newFFI(ffiOpts{
+ sym: "opendal_metadata_is_dir",
rType: &ffi.TypeUint8,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) metaIsDir {
+}, func(ctx context.Context, ffiCall ffiCall) func(m *opendalMetadata) bool {
return func(m *opendalMetadata) bool {
var result uint8
ffiCall(
@@ -142,15 +125,11 @@ var withMetaIsDir = withFFI(ffiOpts{
}
})
-type metaLastModified func(m *opendalMetadata) int64
-
-const symMetadataLastModified = "opendal_metadata_last_modified_ms"
-
-var withMetaLastModified = withFFI(ffiOpts{
- sym: symMetadataLastModified,
+var ffiMetaLastModified = newFFI(ffiOpts{
+ sym: "opendal_metadata_last_modified_ms",
rType: &ffi.TypeSint64,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) metaLastModified {
+}, func(ctx context.Context, ffiCall ffiCall) func(m *opendalMetadata) int64 {
return func(m *opendalMetadata) int64 {
var result int64
ffiCall(
@@ -161,15 +140,11 @@ var withMetaLastModified = withFFI(ffiOpts{
}
})
-type metaFree func(m *opendalMetadata)
-
-const symMetadataFree = "opendal_metadata_free"
-
-var withMetaFree = withFFI(ffiOpts{
- sym: symMetadataFree,
+var ffiMetadataFree = newFFI(ffiOpts{
+ sym: "opendal_metadata_free",
rType: &ffi.TypeVoid,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) metaFree {
+}, func(ctx context.Context, ffiCall ffiCall) func(m *opendalMetadata) {
return func(m *opendalMetadata) {
ffiCall(
nil,
diff --git a/bindings/go/opendal.go b/bindings/go/opendal.go
index 86b80b853..ab2777878 100644
--- a/bindings/go/opendal.go
+++ b/bindings/go/opendal.go
@@ -171,16 +171,15 @@ func NewOperator(scheme Scheme, opts OperatorOptions) (op
*Operator, err error)
return
}
- ctx, cancel, err := contextWithFFIs(scheme.Path())
+ ctx, cancel, err := newContext(scheme.Path())
if err != nil {
return
}
- options := getFFI[operatorOptionsNew](ctx, symOperatorOptionsNew)()
- setOptions := getFFI[operatorOptionsSet](ctx, symOperatorOptionSet)
- optionsFree := getFFI[operatorOptionsFree](ctx, symOperatorOptionsFree)
+ options := ffiOperatorOptionsNew.symbol(ctx)()
+ setOptions := ffiOperatorOptionsSet.symbol(ctx)
- defer optionsFree(options)
+ defer ffiOperatorOptionsFree.symbol(ctx)(options)
for key, value := range opts {
err = setOptions(options, key, value)
@@ -189,7 +188,7 @@ func NewOperator(scheme Scheme, opts OperatorOptions) (op
*Operator, err error)
}
}
- inner, err := getFFI[operatorNew](ctx, symOperatorNew)(scheme, options)
+ inner, err := ffiOperatorNew.symbol(ctx)(scheme, options)
if err != nil {
cancel()
return
@@ -211,7 +210,6 @@ func NewOperator(scheme Scheme, opts OperatorOptions) (op
*Operator, err error)
//
// Note: It's recommended to use defer op.Close() immediately after creating
an Operator.
func (op *Operator) Close() {
- free := getFFI[operatorFree]
- free(op.ctx, symOperatorFree)(op.inner)
+ ffiOperatorFree.symbol(op.ctx)(op.inner)
op.cancel()
}
diff --git a/bindings/go/operator.go b/bindings/go/operator.go
index c3ba125f7..46a996033 100644
--- a/bindings/go/operator.go
+++ b/bindings/go/operator.go
@@ -59,8 +59,7 @@ import (
//
// Note: This example assumes proper error handling and import statements.
func (op *Operator) Copy(src, dest string) error {
- cp := getFFI[operatorCopy](op.ctx, symOperatorCopy)
- return cp(op.inner, src, dest)
+ return ffiOperatorCopy.symbol(op.ctx)(op.inner, src, dest)
}
// Rename changes the name or location of a file from the source path to the
destination path.
@@ -95,24 +94,19 @@ func (op *Operator) Copy(src, dest string) error {
//
// Note: This example assumes proper error handling and import statements.
func (op *Operator) Rename(src, dest string) error {
- rename := getFFI[operatorRename](op.ctx, symOperatorRename)
- return rename(op.inner, src, dest)
+ return ffiOperatorRename.symbol(op.ctx)(op.inner, src, dest)
}
-const symOperatorNew = "opendal_operator_new"
-
-type operatorNew func(scheme Scheme, opts *operatorOptions) (op
*opendalOperator, err error)
-
-var withOperatorNew = withFFI(ffiOpts{
- sym: symOperatorNew,
+var ffiOperatorNew = newFFI(ffiOpts{
+ sym: "opendal_operator_new",
rType: &typeResultOperatorNew,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorNew {
+}, func(ctx context.Context, ffiCall ffiCall) func(scheme Scheme, opts
*operatorOptions) (op *opendalOperator, err error) {
return func(scheme Scheme, opts *operatorOptions) (op *opendalOperator,
err error) {
var byteName *byte
byteName, err = BytePtrFromString(scheme.Name())
if err != nil {
- return
+ return nil, err
}
var result resultOperatorNew
ffiCall(
@@ -129,15 +123,11 @@ var withOperatorNew = withFFI(ffiOpts{
}
})
-const symOperatorFree = "opendal_operator_free"
-
-type operatorFree func(op *opendalOperator)
-
-var withOperatorFree = withFFI(ffiOpts{
- sym: symOperatorFree,
+var ffiOperatorFree = newFFI(ffiOpts{
+ sym: "opendal_operator_free",
rType: &ffi.TypeVoid,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(_ context.Context, ffiCall ffiCall) operatorFree {
+}, func(_ context.Context, ffiCall ffiCall) func(op *opendalOperator) {
return func(op *opendalOperator) {
ffiCall(
nil,
@@ -148,29 +138,21 @@ var withOperatorFree = withFFI(ffiOpts{
type operatorOptions struct{}
-const symOperatorOptionsNew = "opendal_operator_options_new"
-
-type operatorOptionsNew func() (opts *operatorOptions)
-
-var withOperatorOptionsNew = withFFI(ffiOpts{
- sym: symOperatorOptionsNew,
+var ffiOperatorOptionsNew = newFFI(ffiOpts{
+ sym: "opendal_operator_options_new",
rType: &ffi.TypePointer,
-}, func(_ context.Context, ffiCall ffiCall) operatorOptionsNew {
+}, func(_ context.Context, ffiCall ffiCall) func() (opts *operatorOptions) {
return func() (opts *operatorOptions) {
ffiCall(unsafe.Pointer(&opts))
return
}
})
-const symOperatorOptionSet = "opendal_operator_options_set"
-
-type operatorOptionsSet func(opts *operatorOptions, key, value string) error
-
-var withOperatorOptionsSet = withFFI(ffiOpts{
- sym: symOperatorOptionSet,
+var ffiOperatorOptionsSet = newFFI(ffiOpts{
+ sym: "opendal_operator_options_set",
rType: &ffi.TypeVoid,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer,
&ffi.TypePointer},
-}, func(_ context.Context, ffiCall ffiCall) operatorOptionsSet {
+}, func(_ context.Context, ffiCall ffiCall) func(opts *operatorOptions, key,
value string) (err error) {
return func(opts *operatorOptions, key, value string) (err error) {
var (
byteKey *byte
@@ -194,15 +176,11 @@ var withOperatorOptionsSet = withFFI(ffiOpts{
}
})
-const symOperatorOptionsFree = "opendal_operator_options_free"
-
-type operatorOptionsFree func(opts *operatorOptions)
-
-var withOperatorOptionsFree = withFFI(ffiOpts{
- sym: symOperatorOptionsFree,
+var ffiOperatorOptionsFree = newFFI(ffiOpts{
+ sym: "opendal_operator_options_free",
rType: &ffi.TypeVoid,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(_ context.Context, ffiCall ffiCall) operatorOptionsFree {
+}, func(_ context.Context, ffiCall ffiCall) func(opts *operatorOptions) {
return func(opts *operatorOptions) {
ffiCall(
nil,
@@ -211,15 +189,11 @@ var withOperatorOptionsFree = withFFI(ffiOpts{
}
})
-const symOperatorCopy = "opendal_operator_copy"
-
-type operatorCopy func(op *opendalOperator, src, dest string) (err error)
-
-var withOperatorCopy = withFFI(ffiOpts{
- sym: symOperatorCopy,
+var ffiOperatorCopy = newFFI(ffiOpts{
+ sym: "opendal_operator_copy",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer,
&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorCopy {
+}, func(ctx context.Context, ffiCall ffiCall) func(op *opendalOperator, src,
dest string) (err error) {
return func(op *opendalOperator, src, dest string) (err error) {
var (
byteSrc *byte
@@ -244,15 +218,11 @@ var withOperatorCopy = withFFI(ffiOpts{
}
})
-const symOperatorRename = "opendal_operator_rename"
-
-type operatorRename func(op *opendalOperator, src, dest string) (err error)
-
-var withOperatorRename = withFFI(ffiOpts{
- sym: symOperatorRename,
+var ffiOperatorRename = newFFI(ffiOpts{
+ sym: "opendal_operator_rename",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer,
&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorRename {
+}, func(ctx context.Context, ffiCall ffiCall) func(op *opendalOperator, src,
dest string) (err error) {
return func(op *opendalOperator, src, dest string) (err error) {
var (
byteSrc *byte
@@ -277,15 +247,11 @@ var withOperatorRename = withFFI(ffiOpts{
}
})
-const symBytesFree = "opendal_bytes_free"
-
-type bytesFree func(b *opendalBytes)
-
-var withBytesFree = withFFI(ffiOpts{
- sym: symBytesFree,
+var ffiBytesFree = newFFI(ffiOpts{
+ sym: "opendal_bytes_free",
rType: &ffi.TypeVoid,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(_ context.Context, ffiCall ffiCall) bytesFree {
+}, func(ctx context.Context, ffiCall ffiCall) func(b *opendalBytes) {
return func(b *opendalBytes) {
ffiCall(
nil,
diff --git a/bindings/go/operator_info.go b/bindings/go/operator_info.go
index 89ff932ca..ca02ed2dd 100644
--- a/bindings/go/operator_info.go
+++ b/bindings/go/operator_info.go
@@ -34,23 +34,15 @@ import (
// Returns:
// - *OperatorInfo: A pointer to an OperatorInfo struct containing the
Operator's metadata.
func (op *Operator) Info() *OperatorInfo {
- newInfo := getFFI[operatorInfoNew](op.ctx, symOperatorInfoNew)
- inner := newInfo(op.inner)
- getFullCap := getFFI[operatorInfoGetFullCapability](op.ctx,
symOperatorInfoGetFullCapability)
- getNativeCap := getFFI[operatorInfoGetNativeCapability](op.ctx,
symOperatorInfoGetNativeCapability)
- getScheme := getFFI[operatorInfoGetScheme](op.ctx,
symOperatorInfoGetScheme)
- getRoot := getFFI[operatorInfoGetRoot](op.ctx, symOperatorInfoGetRoot)
- getName := getFFI[operatorInfoGetName](op.ctx, symOperatorInfoGetName)
-
- free := getFFI[operatorInfoFree](op.ctx, symOperatorInfoFree)
- defer free(inner)
+ inner := ffiOperatorInfoNew.symbol(op.ctx)(op.inner)
+ defer ffiOperatorInfoFree.symbol(op.ctx)(inner)
return &OperatorInfo{
- scheme: getScheme(inner),
- root: getRoot(inner),
- name: getName(inner),
- fullCap: &Capability{inner: getFullCap(inner)},
- nativeCap: &Capability{inner: getNativeCap(inner)},
+ scheme: ffiOperatorInfoGetScheme.symbol(op.ctx)(inner),
+ root: ffiOperatorInfoGetRoot.symbol(op.ctx)(inner),
+ name: ffiOperatorInfoGetName.symbol(op.ctx)(inner),
+ fullCap: &Capability{inner:
ffiOperatorInfoGetFullCapability.symbol(op.ctx)(inner)},
+ nativeCap: &Capability{inner:
ffiOperatorInfoGetNativeCapability.symbol(op.ctx)(inner)},
}
}
@@ -235,15 +227,11 @@ func (c *Capability) Blocking() bool {
return c.inner.blocking == 1
}
-const symOperatorInfoNew = "opendal_operator_info_new"
-
-type operatorInfoNew func(op *opendalOperator) *opendalOperatorInfo
-
-var withOperatorInfoNew = withFFI(ffiOpts{
- sym: symOperatorInfoNew,
+var ffiOperatorInfoNew = newFFI(ffiOpts{
+ sym: "opendal_operator_info_new",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorInfoNew {
+}, func(ctx context.Context, ffiCall ffiCall) func(op *opendalOperator)
*opendalOperatorInfo {
return func(op *opendalOperator) *opendalOperatorInfo {
var result *opendalOperatorInfo
ffiCall(
@@ -254,15 +242,11 @@ var withOperatorInfoNew = withFFI(ffiOpts{
}
})
-const symOperatorInfoFree = "opendal_operator_info_free"
-
-type operatorInfoFree func(info *opendalOperatorInfo)
-
-var withOperatorInfoFree = withFFI(ffiOpts{
- sym: symOperatorInfoFree,
+var ffiOperatorInfoFree = newFFI(ffiOpts{
+ sym: "opendal_operator_info_free",
rType: &ffi.TypeVoid,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorInfoFree {
+}, func(_ context.Context, ffiCall ffiCall) func(info *opendalOperatorInfo) {
return func(info *opendalOperatorInfo) {
ffiCall(
nil,
@@ -271,15 +255,11 @@ var withOperatorInfoFree = withFFI(ffiOpts{
}
})
-const symOperatorInfoGetFullCapability =
"opendal_operator_info_get_full_capability"
-
-type operatorInfoGetFullCapability func(info *opendalOperatorInfo)
*opendalCapability
-
-var withOperatorInfoGetFullCapability = withFFI(ffiOpts{
- sym: symOperatorInfoGetFullCapability,
+var ffiOperatorInfoGetFullCapability = newFFI(ffiOpts{
+ sym: "opendal_operator_info_get_full_capability",
rType: &typeCapability,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorInfoGetFullCapability {
+}, func(ctx context.Context, ffiCall ffiCall) func(info *opendalOperatorInfo)
*opendalCapability {
return func(info *opendalOperatorInfo) *opendalCapability {
var cap opendalCapability
ffiCall(
@@ -290,15 +270,11 @@ var withOperatorInfoGetFullCapability = withFFI(ffiOpts{
}
})
-const symOperatorInfoGetNativeCapability =
"opendal_operator_info_get_native_capability"
-
-type operatorInfoGetNativeCapability func(info *opendalOperatorInfo)
*opendalCapability
-
-var withOperatorInfoGetNativeCapability = withFFI(ffiOpts{
- sym: symOperatorInfoGetNativeCapability,
+var ffiOperatorInfoGetNativeCapability = newFFI(ffiOpts{
+ sym: "opendal_operator_info_get_native_capability",
rType: &typeCapability,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorInfoGetNativeCapability {
+}, func(ctx context.Context, ffiCall ffiCall) func(info *opendalOperatorInfo)
*opendalCapability {
return func(info *opendalOperatorInfo) *opendalCapability {
var cap opendalCapability
ffiCall(
@@ -309,15 +285,11 @@ var withOperatorInfoGetNativeCapability = withFFI(ffiOpts{
}
})
-const symOperatorInfoGetScheme = "opendal_operator_info_get_scheme"
-
-type operatorInfoGetScheme func(info *opendalOperatorInfo) string
-
-var withOperatorInfoGetScheme = withFFI(ffiOpts{
- sym: symOperatorInfoGetScheme,
+var ffiOperatorInfoGetScheme = newFFI(ffiOpts{
+ sym: "opendal_operator_info_get_scheme",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorInfoGetScheme {
+}, func(ctx context.Context, ffiCall ffiCall) func(info *opendalOperatorInfo)
string {
return func(info *opendalOperatorInfo) string {
var bytePtr *byte
ffiCall(
@@ -328,15 +300,11 @@ var withOperatorInfoGetScheme = withFFI(ffiOpts{
}
})
-const symOperatorInfoGetRoot = "opendal_operator_info_get_root"
-
-type operatorInfoGetRoot func(info *opendalOperatorInfo) string
-
-var withOperatorInfoGetRoot = withFFI(ffiOpts{
- sym: symOperatorInfoGetRoot,
+var ffiOperatorInfoGetRoot = newFFI(ffiOpts{
+ sym: "opendal_operator_info_get_root",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorInfoGetRoot {
+}, func(ctx context.Context, ffiCall ffiCall) func(info *opendalOperatorInfo)
string {
return func(info *opendalOperatorInfo) string {
var bytePtr *byte
ffiCall(
@@ -347,15 +315,11 @@ var withOperatorInfoGetRoot = withFFI(ffiOpts{
}
})
-const symOperatorInfoGetName = "opendal_operator_info_get_name"
-
-type operatorInfoGetName func(info *opendalOperatorInfo) string
-
-var withOperatorInfoGetName = withFFI(ffiOpts{
- sym: symOperatorInfoGetName,
+var ffiOperatorInfoGetName = newFFI(ffiOpts{
+ sym: "opendal_operator_info_get_name",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorInfoGetName {
+}, func(ctx context.Context, ffiCall ffiCall) func(info *opendalOperatorInfo)
string {
return func(info *opendalOperatorInfo) string {
var bytePtr *byte
ffiCall(
diff --git a/bindings/go/reader.go b/bindings/go/reader.go
index 3dde9ce68..346bce199 100644
--- a/bindings/go/reader.go
+++ b/bindings/go/reader.go
@@ -58,16 +58,14 @@ import (
//
// Note: This example assumes proper error handling and import statements.
func (op *Operator) Read(path string) ([]byte, error) {
- read := getFFI[operatorRead](op.ctx, symOperatorRead)
- bytes, err := read(op.inner, path)
+ bytes, err := ffiOperatorRead.symbol(op.ctx)(op.inner, path)
if err != nil {
return nil, err
}
data := parseBytes(bytes)
if len(data) > 0 {
- free := getFFI[bytesFree](op.ctx, symBytesFree)
- free(&bytes)
+ ffiBytesFree.symbol(op.ctx)(&bytes)
}
return data, nil
}
@@ -113,8 +111,7 @@ func (op *Operator) Read(path string) ([]byte, error) {
//
// Note: This example assumes proper error handling and import statements.
func (op *Operator) Reader(path string) (*Reader, error) {
- getReader := getFFI[operatorReader](op.ctx, symOperatorReader)
- inner, err := getReader(op.inner, path)
+ inner, err := ffiOperatorReader.symbol(op.ctx)(op.inner, path)
if err != nil {
return nil, err
}
@@ -177,7 +174,7 @@ func (r *Reader) Read(buf []byte) (int, error) {
if length == 0 {
return 0, nil
}
- read := getFFI[readerRead](r.ctx, symReaderRead)
+ read := ffiReaderRead.symbol(r.ctx)
var (
totalSize uint
size uint
@@ -238,26 +235,20 @@ func (r *Reader) Read(buf []byte) (int, error) {
// Note: The actual new position may differ from the requested position
// if the underlying storage system has restrictions on seeking.
func (r *Reader) Seek(offset int64, whence int) (int64, error) {
- seek := getFFI[readerSeek](r.ctx, symReaderSeek)
- return seek(r.inner, offset, whence)
+ return ffiReaderSeek.symbol(r.ctx)(r.inner, offset, whence)
}
// Close releases resources associated with the OperatorReader.
func (r *Reader) Close() error {
- free := getFFI[readerFree](r.ctx, symReaderFree)
- free(r.inner)
+ ffiReaderFree.symbol(r.ctx)(r.inner)
return nil
}
-const symOperatorRead = "opendal_operator_read"
-
-type operatorRead func(op *opendalOperator, path string) (opendalBytes, error)
-
-var withOperatorRead = withFFI(ffiOpts{
- sym: symOperatorRead,
+var ffiOperatorRead = newFFI(ffiOpts{
+ sym: "opendal_operator_read",
rType: &typeResultRead,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorRead {
+}, func(ctx context.Context, ffiCall ffiCall) func(op *opendalOperator, path
string) (opendalBytes, error) {
return func(op *opendalOperator, path string) (opendalBytes, error) {
bytePath, err := BytePtrFromString(path)
if err != nil {
@@ -273,15 +264,11 @@ var withOperatorRead = withFFI(ffiOpts{
}
})
-const symOperatorReader = "opendal_operator_reader"
-
-type operatorReader func(op *opendalOperator, path string) (*opendalReader,
error)
-
-var withOperatorReader = withFFI(ffiOpts{
- sym: symOperatorReader,
+var ffiOperatorReader = newFFI(ffiOpts{
+ sym: "opendal_operator_reader",
rType: &typeResultOperatorReader,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorReader {
+}, func(ctx context.Context, ffiCall ffiCall) func(op *opendalOperator, path
string) (*opendalReader, error) {
return func(op *opendalOperator, path string) (*opendalReader, error) {
bytePath, err := BytePtrFromString(path)
if err != nil {
@@ -300,15 +287,11 @@ var withOperatorReader = withFFI(ffiOpts{
}
})
-const symReaderFree = "opendal_reader_free"
-
-type readerFree func(r *opendalReader)
-
-var withReaderFree = withFFI(ffiOpts{
- sym: symReaderFree,
+var ffiReaderFree = newFFI(ffiOpts{
+ sym: "opendal_reader_free",
rType: &ffi.TypeVoid,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) readerFree {
+}, func(ctx context.Context, ffiCall ffiCall) func(r *opendalReader) {
return func(r *opendalReader) {
ffiCall(
nil,
@@ -317,15 +300,11 @@ var withReaderFree = withFFI(ffiOpts{
}
})
-const symReaderRead = "opendal_reader_read"
-
-type readerRead func(r *opendalReader, buf []byte) (size uint, err error)
-
-var withReaderRead = withFFI(ffiOpts{
- sym: symReaderRead,
+var ffiReaderRead = newFFI(ffiOpts{
+ sym: "opendal_reader_read",
rType: &typeResultReaderRead,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer,
&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) readerRead {
+}, func(ctx context.Context, ffiCall ffiCall) func(r *opendalReader, buf
[]byte) (size uint, err error) {
return func(r *opendalReader, buf []byte) (size uint, err error) {
var length = len(buf)
if length == 0 {
@@ -346,15 +325,11 @@ var withReaderRead = withFFI(ffiOpts{
}
})
-const symReaderSeek = "opendal_reader_seek"
-
-type readerSeek func(r *opendalReader, offset int64, whence int) (int64, error)
-
-var withReaderSeek = withFFI(ffiOpts{
- sym: symReaderSeek,
+var ffiReaderSeek = newFFI(ffiOpts{
+ sym: "opendal_reader_seek",
rType: &typeResultReaderSeek,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer,
&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) readerSeek {
+}, func(ctx context.Context, ffiCall ffiCall) func(r *opendalReader, offset
int64, whence int) (int64, error) {
return func(r *opendalReader, offset int64, whence int) (int64, error) {
var result resultReaderSeek
ffiCall(
diff --git a/bindings/go/stat.go b/bindings/go/stat.go
index f4a8a6881..a754dbb4c 100644
--- a/bindings/go/stat.go
+++ b/bindings/go/stat.go
@@ -61,8 +61,7 @@ import (
//
// Note: This example assumes proper error handling and import statements.
func (op *Operator) Stat(path string) (*Metadata, error) {
- stat := getFFI[operatorStat](op.ctx, symOperatorStat)
- meta, err := stat(op.inner, path)
+ meta, err := ffiOperatorStat.symbol(op.ctx)(op.inner, path)
if err != nil {
return nil, err
}
@@ -96,19 +95,14 @@ func (op *Operator) Stat(path string) (*Metadata, error) {
// fmt.Println("The file does not exist")
// }
func (op *Operator) IsExist(path string) (bool, error) {
- isExist := getFFI[operatorIsExist](op.ctx, symOperatorIsExist)
- return isExist(op.inner, path)
+ return ffiOperatorIsExist.symbol(op.ctx)(op.inner, path)
}
-const symOperatorStat = "opendal_operator_stat"
-
-type operatorStat func(op *opendalOperator, path string) (*opendalMetadata,
error)
-
-var withOperatorStat = withFFI(ffiOpts{
- sym: symOperatorStat,
+var ffiOperatorStat = newFFI(ffiOpts{
+ sym: "opendal_operator_stat",
rType: &typeResultStat,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorStat {
+}, func(ctx context.Context, ffiCall ffiCall) func(op *opendalOperator, path
string) (*opendalMetadata, error) {
return func(op *opendalOperator, path string) (*opendalMetadata, error)
{
bytePath, err := BytePtrFromString(path)
if err != nil {
@@ -127,15 +121,11 @@ var withOperatorStat = withFFI(ffiOpts{
}
})
-const symOperatorIsExist = "opendal_operator_is_exist"
-
-type operatorIsExist func(op *opendalOperator, path string) (bool, error)
-
-var withOperatorIsExists = withFFI(ffiOpts{
- sym: symOperatorIsExist,
+var ffiOperatorIsExist = newFFI(ffiOpts{
+ sym: "opendal_operator_is_exist",
rType: &typeResultIsExist,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorIsExist {
+}, func(ctx context.Context, ffiCall ffiCall) func(op *opendalOperator, path
string) (bool, error) {
return func(op *opendalOperator, path string) (bool, error) {
bytePath, err := BytePtrFromString(path)
if err != nil {
diff --git a/bindings/go/write.go b/bindings/go/write.go
index 520dcff43..c2d0e5088 100644
--- a/bindings/go/write.go
+++ b/bindings/go/write.go
@@ -54,8 +54,7 @@ import (
//
// Note: This example assumes proper error handling and import statements.
func (op *Operator) Write(path string, data []byte) error {
- write := getFFI[operatorWrite](op.ctx, symOperatorWrite)
- return write(op.inner, path, data)
+ return ffiOperatorWrite.symbol(op.ctx)(op.inner, path, data)
}
// CreateDir creates a directory at the specified path.
@@ -94,8 +93,7 @@ func (op *Operator) Write(path string, data []byte) error {
// Note: This example assumes proper error handling and import statements.
// The trailing slash in "test/" is important to indicate it's a directory.
func (op *Operator) CreateDir(path string) error {
- createDir := getFFI[operatorCreateDir](op.ctx, symOperatorCreateDir)
- return createDir(op.inner, path)
+ return ffiOperatorCreateDir.symbol(op.ctx)(op.inner, path)
}
// Writer returns a new Writer for the specified path.
@@ -127,9 +125,7 @@ func (op *Operator) CreateDir(path string) error {
//
// Note: This example assumes proper error handling and import statements.
func (op *Operator) Writer(path string) (*Writer, error) {
- getWriter := getFFI[operatorWriter](op.ctx,
- symOperatorWriter)
- inner, err := getWriter(op.inner, path)
+ inner, err := ffiOperatorWriter.symbol(op.ctx)(op.inner, path)
if err != nil {
return nil, err
}
@@ -173,31 +169,24 @@ type Writer struct {
//
// Note: This example assumes proper error handling and import statements.
func (w *Writer) Write(p []byte) (n int, err error) {
- write := getFFI[writerWrite](w.ctx, symWriterWrite)
- return write(w.inner, p)
+ return ffiWriterWrite.symbol(w.ctx)(w.inner, p)
}
// Close finishes the write and releases the resources associated with the
Writer.
// It is important to call Close after writing all the data to ensure that the
data is
// properly flushed and written to the storage. Otherwise, the data may be
lost.
func (w *Writer) Close() error {
- free := getFFI[writerFree](w.ctx, symWriterFree)
- defer free(w.inner)
- close := getFFI[writerClose](w.ctx, symWriterClose)
- return close(w.inner)
+ defer ffiWriterFree.symbol(w.ctx)(w.inner)
+ return ffiWriterClose.symbol(w.ctx)(w.inner)
}
var _ io.WriteCloser = (*Writer)(nil)
-const symOperatorWrite = "opendal_operator_write"
-
-type operatorWrite func(op *opendalOperator, path string, data []byte) error
-
-var withOperatorWrite = withFFI(ffiOpts{
- sym: symOperatorWrite,
+var ffiOperatorWrite = newFFI(ffiOpts{
+ sym: "opendal_operator_write",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer,
&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorWrite {
+}, func(ctx context.Context, ffiCall ffiCall) func(op *opendalOperator, path
string, data []byte) error {
return func(op *opendalOperator, path string, data []byte) error {
bytePath, err := BytePtrFromString(path)
if err != nil {
@@ -215,15 +204,11 @@ var withOperatorWrite = withFFI(ffiOpts{
}
})
-const symOperatorCreateDir = "opendal_operator_create_dir"
-
-type operatorCreateDir func(op *opendalOperator, path string) error
-
-var withOperatorCreateDir = withFFI(ffiOpts{
- sym: symOperatorCreateDir,
+var ffiOperatorCreateDir = newFFI(ffiOpts{
+ sym: "opendal_operator_create_dir",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorCreateDir {
+}, func(ctx context.Context, ffiCall ffiCall) func(op *opendalOperator, path
string) error {
return func(op *opendalOperator, path string) error {
bytePath, err := BytePtrFromString(path)
if err != nil {
@@ -239,15 +224,11 @@ var withOperatorCreateDir = withFFI(ffiOpts{
}
})
-const symOperatorWriter = "opendal_operator_writer"
-
-type operatorWriter func(op *opendalOperator, path string) (*opendalWriter,
error)
-
-var withOperatorWriter = withFFI(ffiOpts{
- sym: symOperatorWriter,
+var ffiOperatorWriter = newFFI(ffiOpts{
+ sym: "opendal_operator_writer",
rType: &typeResultOperatorWriter,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) operatorWriter {
+}, func(ctx context.Context, ffiCall ffiCall) func(op *opendalOperator, path
string) (*opendalWriter, error) {
return func(op *opendalOperator, path string) (*opendalWriter, error) {
bytePath, err := BytePtrFromString(path)
if err != nil {
@@ -266,34 +247,26 @@ var withOperatorWriter = withFFI(ffiOpts{
}
})
-const symWriterFree = "opendal_writer_free"
-
-type writerFree func(w *opendalWriter)
-
-var withWriterFree = withFFI(ffiOpts{
- sym: symWriterFree,
+var ffiWriterFree = newFFI(ffiOpts{
+ sym: "opendal_writer_free",
rType: &ffi.TypeVoid,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) writerFree {
- return func(r *opendalWriter) {
+}, func(ctx context.Context, ffiCall ffiCall) func(w *opendalWriter) {
+ return func(w *opendalWriter) {
ffiCall(
nil,
- unsafe.Pointer(&r),
+ unsafe.Pointer(&w),
)
}
})
-const symWriterWrite = "opendal_writer_write"
-
-type writerWrite func(r *opendalWriter, buf []byte) (size int, err error)
-
-var withWriterWrite = withFFI(ffiOpts{
- sym: symWriterWrite,
+var ffiWriterWrite = newFFI(ffiOpts{
+ sym: "opendal_writer_write",
rType: &typeResultWriterWrite,
aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) writerWrite {
- return func(r *opendalWriter, data []byte) (size int, err error) {
- bytes := toOpendalBytes(data)
+}, func(ctx context.Context, ffiCall ffiCall) func(r *opendalWriter, buf
[]byte) (size int, err error) {
+ return func(r *opendalWriter, buf []byte) (size int, err error) {
+ bytes := toOpendalBytes(buf)
var result resultWriterWrite
ffiCall(
unsafe.Pointer(&result),
@@ -307,15 +280,11 @@ var withWriterWrite = withFFI(ffiOpts{
}
})
-const symWriterClose = "opendal_writer_close"
-
-type writerClose func(r *opendalWriter) error
-
-var withWriterClose = withFFI(ffiOpts{
- sym: symWriterClose,
+var ffiWriterClose = newFFI(ffiOpts{
+ sym: "opendal_writer_close",
rType: &ffi.TypePointer,
aTypes: []*ffi.Type{&ffi.TypePointer},
-}, func(ctx context.Context, ffiCall ffiCall) writerClose {
+}, func(ctx context.Context, ffiCall ffiCall) func(r *opendalWriter) error {
return func(r *opendalWriter) error {
var e *opendalError
ffiCall(