apache / opendal

Apache OpenDAL: access data freely.
https://opendal.apache.org
Apache License 2.0
3k stars 416 forks source link

idea: Go bindings **Native** support without CGO #4848

Open yuchanns opened 2 days ago

yuchanns commented 2 days ago

Hello community!

I'd like to introduce you to a native method for supporting Go bindings without CGO.

This capability primarily relies on two libraries: purego and libffi.

To support the passing and returning of structure values, we need to create lightweight Go libffi bindings by wrapping purego, which is already provided by ffi. We can either use it or maintain it ourselves directly.

Then we can call arbitrary C functions using libffi from Go without enabling CGO, which is why I refer to it as Native support!

Here's a POC that demonstrates its functionality with backend memory and aliyun_drive: gopendal.

Pros:

Cons:

What do you think? I look forward to your comments!

yuchanns commented 2 days ago

Source: https://github.com/ebitengine/purego/issues/236

Xuanwo commented 2 days ago

Adding some context:

We have discussed similiar ideas in the past.


  • Still requires libopendal_c.so. - We can embed it in go files for each platform_suffix file. eg: _linux.go, _windows.go,

From the ASF perspective, distributing binaries in source form is not permitted. Therefore, we might not include in this repo directly. Perhaps we could set up an additional repository for releases.

yuchanns commented 2 days ago

From the ASF perspective, distributing binaries in source form is not permitted.

I add a pros: Dynamic Inject distributing binaries. It can be an advantage as current features of bindings can not be controlled by users.

Xuanwo commented 2 days ago
  • Depends on preinstalled libffi. - libffi is widely used in many languages and commonly preinstalled on many platforms. You can easily install it with the package manager if not available.

Confirmed. libffi is widely pre-installed and depended:

https://archlinux.org/packages/core/x86_64/libffi/

image

zjregee commented 2 days ago

Looking forward to this!

yuchanns commented 2 days ago

Adding some context:

Ok, I've checked the context, and identified some major blockers:

Well, these are truly obstacles. I've no idea how to resolve them.

TBH, I do think it is impossible to support subdirectories in the foreseeable future as the Go team prioritizes things based on their needs. Even if the problem has been resolved, we still have to challenge the binary distribution as Go is not designed to be extended with other languages.

IMO, it is inevitable to have multiple root repos for go bindings of various features. As long as these sources are distributed under opendal.apache.org/go, users can trust them, and no need to care where are they placed.

As for the *.so binaries, they can be loaded separately just like various dialects in gorm.io/driver/{sqlite,mysql,postgres}.

That is to say:

package main

import (
    opendal "opendal.apache.org/go"
    _ "opendal.some.others/services/s3" // this dynamic inject *.so
)

I regret that these guideline-level issues have prevented the implementation of go-binding.

Xuanwo commented 2 days ago
package main

import (
  opendal "opendal.apache.org/go"
  _ "opendal.some.others/services/s3" // this dynamic inject *.so
)

Wow, I didn't know that was possible! I think we can start with github.com/apache/opendal/bindings/go and your own "*.so" files to see how it functions. If it works well, I'm willing to help manage the artifacts by setting up a new repository called github.com/apache/opendal-go-artifacts (just for example).

yuchanns commented 2 days ago

I think we can start with github.com/apache/opendal/bindings/go and your own "*.so" files to see how it functions.

Cool. I will take a try next week.