-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Struct support on Linux #236
Comments
Maybe it is possible to write a wrapper using libffi. |
My biggest concern is maintaining the code for each platform. Structs support on Darwin is more complicated than handling all other return and argument types for all platforms combined. Even if most of the code is the same I do not have easy access to these platforms to test and validate the accuracy of the implementations. Just see the stalling of #234 The current goal right now is supporting Ebitengine and as this is not needed right now for it this feature will have to wait. Of course this is not a complete write off and it may happen in the future. |
I finally have a working example:
//go:build linux && amd64
// +build linux,amd64
package ffi
import (
"unsafe"
"github.com/ebitengine/purego"
)
func init() {
handle, err := purego.Dlopen("libffi.so", purego.RTLD_LAZY)
if err != nil {
panic(err)
}
purego.RegisterLibFunc(&PrepCif, handle, "ffi_prep_cif")
purego.RegisterLibFunc(&Call, handle, "ffi_call")
}
type Abi uint32
const (
DefaultAbi Abi = 2
)
type Status uint32
const (
OK Status = 0
)
const (
Void = 0
Double = 3
Float = 2
Sint32 = 10
Pointer = 14
)
type Typ struct {
Size uint64
Alignment uint16
Typ uint16
Elements **Typ
}
var (
TypDouble = Typ{8, 8, Double, nil}
TypVoid = Typ{1, 1, Void, nil}
TypPointer = Typ{8, 8, Pointer, nil}
TypSint32 = Typ{4, 4, Sint32, nil}
TypFloat = Typ{4, 4, Float, nil}
)
type Cif struct {
Abi uint32
Nargs uint32
ArgTypes **Typ
RTyp *Typ
Bytes uint32
Flags uint32
}
var PrepCif func(cif *Cif, abi Abi, nargs uint32, rtyp *Typ, atypes []*Typ) Status
var Call func(cif *Cif, fn uintptr, rvalue unsafe.Pointer, avalue []unsafe.Pointer)
//go:build linux && amd64
// +build linux,amd64
package main
import (
"bar/ffi"
"fmt"
"unsafe"
"github.com/ebitengine/purego"
)
func main() {
// load the the library we want to use
raylib, err := purego.Dlopen("libraylib.so", purego.RTLD_LAZY)
if err != nil {
panic(err)
}
defer purego.Dlclose(raylib)
// look for the symbol (function)
vector3Normalize, err := purego.Dlsym(raylib, "Vector3Normalize") // RMAPI Vector3 Vector3Normalize(Vector3 v)
if err != nil {
panic(err)
}
// define the related golang type
type Vector3 struct {
X, Y, Z float32
}
// create the blueprint (description) of how the return value and arguments look like
elements := []*ffi.Typ{&ffi.TypFloat, &ffi.TypFloat, &ffi.TypFloat, nil}
vec3Typ := ffi.Typ{Size: 0, Alignment: 0, Typ: 13, Elements: &elements[0]}
args := []*ffi.Typ{&vec3Typ}
// prepare the function signature
var cif ffi.Cif
if ok := ffi.PrepCif(&cif, ffi.DefaultAbi, 1, &vec3Typ, args); ok != ffi.OK {
panic("cif prep is not OK")
}
// call the function
var rv Vector3
v := Vector3{1, 1, 1}
av := []unsafe.Pointer{unsafe.Pointer(&v)}
ffi.Call(&cif, vector3Normalize, unsafe.Pointer(&rv), av)
fmt.Printf("%+v\n", rv)
} Prints @TotallyGamerJet |
Sure if you want to open source it. |
Repo is here. Feedback is welcome: I also added examples. |
As far as I understand, we need to describe C-type on Go side, like in this example we have I am trying to use it for this struct: Struct
|
@ring-c For a bool u can try to use |
It looks like it must be
Seems like you need to export variable so i can pass path to
Tested with How exactly go-struct maps to |
@ring-c The order of the go-type and the c-type should be the same. If you have any further questions, feel free to open an issue in the ffi repository, so we don't spam this one too much :D |
I think this should stay open so that others can see the workaround. And maybe purego will someday support this feature. |
Operating System
What feature would you like to be added?
this
Can we please have support of sending structs as arguments on linux?
I am willing to test code if required.
Why is this needed?
No response
The text was updated successfully, but these errors were encountered: