-
Notifications
You must be signed in to change notification settings - Fork 0
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
Request for Flutter FFI and Golang tutorials. #3
Comments
This might help you to get started. https://pub.dev/packages/dexecve |
It's not exactly FFI. Looks like it's some sort of hacky way of calling a native executable. It involve:
I have been trying to integrate golang into my flutter app for a very long time now, but I am not able to figure out nativeport support for golang |
Yes it is a hack .. but has some indications about how to proceed in current scenario. |
Accessing go native functions from dart is pretty easy but unfortunately that will block the main event thread. Recently dart added a way to execute the native calls in async way which also gives us callback feature (native code calls a dart function) and this one seems to be bit trickier. I have been trying to get it done but I get stuck at the native port.
Thank you. Much appreciated. Do tag me here if that happens. Thanks again. Have a nice one |
There is a new repo which explains how to get this done. |
https://pub.dev/packages/ffigen is quite helpful. I use this for generating code from c header which is generated from Go. Also refer to golang/go#35715 |
Awesome! |
One of our app https://play.google.com/store/apps/details?id=plus.fitzy.fitzy_app uses these extensively. |
I have a question though. Is there anyway to pack a static library along with go? For compiling a program in Go i need to have libusb pre installed on my mac. The app runs fine if I install libusb via brew. But when I try to run the app in a different machine it says the static library is missing. Is there a way to bundle the dylib file of a library along with the Go program? Checked everywhere couldnt get this working |
I didn't try that. First create a flutter plugin with cmake build and then use the plugin through Dart class. There are some interesting discussions available here. |
Actually this is not for a Flutter app. I need it for a executable that I am building for one of my projects. Thanks anyway! |
I didn't compile the code but I think you need to use WorkStruct as a
pointer in the function argument.
- Archan
…On Sun, Aug 9, 2020 at 2:49 PM Ganesh Rathinavel ***@***.***> wrote:
@archanpaul <https://github.com/archanpaul> Hope you are doing well.
I am trying to write a code to send value from Dart to Go and return a
value back as well. I have been trying to return a struct from Go but
unfortunately I am unable to do that.
main.go
import (
"./dart_api_dl"
"C"
"fmt"
"time"
"unsafe"
)
//export InitializeDartApifunc InitializeDartApi(api unsafe.Pointer) {
dart_api_dl.Init(api)
}
//export StartWorkfunc StartWork(port int64) {
fmt.Println("Go: Starting some asynchronous work")
go func(port int64) {
var counter int64
for {
time.Sleep(2 * time.Second)
fmt.Println("GO: 2 seconds passed")
counter++
value := dart_api_dl.WorkStruct{
Counter: 0,
Name: "Ganesh",
}
dart_api_dl.SendToPort(port, value)
}
}(port)
fmt.Println("Go: Returning to Dart")
}
dart_api_dl.go
package dart_api_dl
// #include "stdint.h"// #include "include/dart_api_dl.c"//// // Go does not allow calling C function pointers directly. So we are// // forced to provide a trampoline.// bool GoDart_PostCObject(Dart_Port_DL port, Dart_CObject* obj) {// return Dart_PostCObject_DL(port, obj);// }import "C"import "unsafe"
//export WorkStructtype WorkStruct struct {
Counter int
Name string
}
func Init(api unsafe.Pointer) C.long {
return C.Dart_InitializeApiDL(api)
}
func SendToPort(port int64, msg WorkStruct) {
var obj C.Dart_CObject
obj._type = C.Dart_CObject_kTypedData
// cgo does not support unions so we are forced to do this
*(*C.struct_WorkStruct)(unsafe.Pointer(&obj.value[0])) = C.struct_WorkStruct(msg)
C.GoDart_PostCObject(C.int64_t(port), &obj)
}
It throws:
dart_api_dl/dart_api_dl.go:28:78: cannot convert msg (type WorkStruct) to type _Ctype_struct_WorkStruct
I am using this repo
<https://github.com/mraleph/go_dart_ffi_example/blob/master/dart_api_dl/dart_api_dl.go>
as the base for writing the FFI code. I just attempted to modify C.int64_t
with C.struct_WorkStruct
Any ideas? Thanks
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#3 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADVX24HHD7TCLLVSYJPC4DR7ZS2ZANCNFSM4PINZIUQ>
.
|
Hey, thanks for the quick reply. I tried to allocate struct to malloc and then send the pointer as int64 to Dart. And then in the dart side I tried to print the value of message returned from Go. But Dart is picking the message from Go as the int 5 which basically ( dart_api_dl.go: // // Go does not allow calling C function pointers directly. So we are
// // forced to provide a trampoline.
// bool GoDart_PostCObject(Dart_Port_DL port, Dart_CObject* obj) {
// return Dart_PostCObject_DL(port, obj);
// }
//
// typedef struct Work{
// int64_t a;
// int64_t b;
// }Work;
//
// void GetWork(void **ppWork) {
// Work *pWork= (Work *)malloc(sizeof(Work));
// pWork->a=5;
// pWork->b=6;
// *ppWork = pWork;
// }
import "C"
func Init(api unsafe.Pointer) C.long {
return C.Dart_InitializeApiDL(api)
}
type Work struct {
a int64
b int64
}
func SendToPort(port int64, msg int64) {
var obj C.Dart_CObject
obj._type = C.Dart_CObject_kInt64
var pwork unsafe.Pointer
C.GetWork(&pwork)
work := *(*Work)(pwork)
unsafePtr := (*int64)(unsafe.Pointer(&work))
*(*C.int64_t)(unsafe.Pointer(&obj.value[0])) = C.int64_t(*unsafePtr)
C.GoDart_PostCObject(C.int64_t(port), &obj)
} Dart side: Future<void> run() async {
_squashArchiverLib.InitializeDartApi(NativeApi.initializeApiDLData);
final interactiveCppRequests = ReceivePort();
final interactiveCppSub = interactiveCppRequests.listen((data) {
print(data); // <---------outputs 5---------->
/*final work = Pointer<Work>.fromAddress(data as int);
print(work.ref.a);
print(work.ref.b);*/
});
final nativePort = interactiveCppRequests.sendPort.nativePort;
_squashArchiverLib.StartWork(nativePort);
} I am not able to return the pointer address of the struct back to Dart, always the value of the struct is returned. Am I doing it right? Any suggestions will be appreciated. |
I got it working. // int64_t GetWork(void **ppWork) {
// Work *pWork= (Work *)malloc(sizeof(Work));
// pWork->a=16;
// pWork->b=15;
// *ppWork = pWork;
//
// int64_t ptr = (int64_t)pWork;
//
// return ptr;
// } func SendToPort(port int64, msg int64) {
var obj C.Dart_CObject
obj._type = C.Dart_CObject_kInt64
var pwork unsafe.Pointer
ptrAddr := C.GetWork(&pwork)
*(*C.int64_t)(unsafe.Pointer(&obj.value[0])) = ptrAddr
C.GoDart_PostCObject(C.int64_t(port), &obj)
defer C.free(pwork)
} Dart side: final interactiveCppSub = interactiveCppRequests.listen((data) {
final work = Pointer<Work>.fromAddress(data as int);
print(work.ref.a);
print(work.ref.b);
});
Thanks a lot for the suggestions. You had been a great help! |
I have not checked your github code thoroughly. Does the following snippet
help?
- Archan
final ffi.DynamicLibrary _dylib;
NativeLibrary(ffi.DynamicLibrary dynamicLibrary) : _dylib =
dynamicLibrary;
*ffi.Pointer*<ffi.Int32> process(
ffi.Pointer<ffi.Int32> x,
) {
_process ??= _dylib.lookupFunction<_c_process,
_dart_process>('process');
return _process(
x,
);
}
C header contains
extern "C" __attribute__((visibility("default"))) __attribute__((used)) int
*process(int *x);
…On Mon, Aug 10, 2020 at 3:35 PM Ganesh Rathinavel ***@***.***> wrote:
Hey, thanks for the quick reply.
I tried to allocate struct to malloc and then send the pointer as int64 to
Dart. And then in the dart side I tried to print the value of message
returned from Go.
But Dart is picking the message from Go as the int *5* which basically (
pWork->a=5;)
dart_api_dl.go:
// // Go does not allow calling C function pointers directly. So we are// // forced to provide a trampoline.// bool GoDart_PostCObject(Dart_Port_DL port, Dart_CObject* obj) {// return Dart_PostCObject_DL(port, obj);// }//// typedef struct Work{// int64_t a;// int64_t b;// }Work;//// void GetWork(void **ppWork) {// Work *pWork= (Work *)malloc(sizeof(Work));// pWork->a=5;// pWork->b=6;// *ppWork = pWork;// }import "C"
func Init(api unsafe.Pointer) C.long {
return C.Dart_InitializeApiDL(api)
}
type Work struct {
a int64
b int64
}
func SendToPort(port int64, msg int64) {
var obj C.Dart_CObject
obj._type = C.Dart_CObject_kInt64
var pwork unsafe.Pointer
C.GetWork(&pwork)
work := *(*Work)(pwork)
unsafePtr := (*int64)(unsafe.Pointer(&work))
*(*C.int64_t)(unsafe.Pointer(&obj.value[0])) = C.int64_t(*unsafePtr)
C.GoDart_PostCObject(C.int64_t(port), &obj)
}
Dart side:
Future<void> run() async {
_squashArchiverLib.InitializeDartApi(NativeApi.initializeApiDLData);
final interactiveCppRequests = ReceivePort();
final interactiveCppSub = interactiveCppRequests.listen((data) {
print(data); // <---------outputs 5---------->
/*final work = Pointer<Work>.fromAddress(data as int); print(work.ref.a); print(work.ref.b);*/
});
final nativePort = interactiveCppRequests.sendPort.nativePort;
_squashArchiverLib.StartWork(nativePort);
}
Git repo:
https://github.com/ganeshrvel/squash_archiver/blob/feature/go-archiver-example/packages/archiver_ffi/native/archiver_lib/dart_api_dl/dart_api_dl.go
I am not able to return the pointer address of the struct back to Dart,
always the value of the struct is returned. Am I doing it right? Any
suggestions will be appreciated.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#3 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADVX22SGRFPB7MQWAVJZVLR77A7HANCNFSM4PINZIUQ>
.
|
Great !!
…On Mon, Aug 10, 2020 at 4:29 PM Ganesh Rathinavel ***@***.***> wrote:
I got it working.
If anyone else is looking for an answer here, this is what i did. I first
did a cast of the struct ptr using uint64_t in the GetWork and returned
the value back.
// uint64_t GetWork(void **ppWork) {// Work *pWork= (Work *)malloc(sizeof(Work));// pWork->a=16;// pWork->b=15;// *ppWork = pWork;// uint64_t ptr = (uint64_t)pWork;// return ptr;// }
func SendToPort(port int64, msg int64) {
var obj C.Dart_CObject
obj._type = C.Dart_CObject_kInt64
var pwork unsafe.Pointer
ptrAddr := C.GetWork(&pwork)
*(*C.uint64_t)(unsafe.Pointer(&obj.value[0])) = ptrAddr
C.GoDart_PostCObject(C.int64_t(port), &obj)
}
Dart side:
final interactiveCppSub = interactiveCppRequests.listen((data) {
// print(data);
final work = Pointer<Work>.fromAddress(data as int);
print(work.ref.a);
print(work.ref.b);
});
Thanks a lot for the suggestions. You had literally been a great help!
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#3 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADVX25JZODWLLJLB7TMG5TR77HJDANCNFSM4PINZIUQ>
.
|
The repo tutorial uses Gomobile for Android and iOS as (#2 indicates this solution won't work for Desktop). Does this new direction of using Dart FFI sound like a solution would work for both mobile and desktops? |
Yes.
…On Mon, Feb 28, 2022, 07:21 Jingsheng Wang ***@***.***> wrote:
The repo tutorial uses Gomobile for Android and iOS as (#2
<#2> indicates
this solution won't work for Desktop). Does this new direction of using
Dart FFI sound like a solution would work for both mobile and desktops?
—
Reply to this email directly, view it on GitHub
<#3 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADVX2433UCPVVSAQIHFF2TU5LIIJANCNFSM4PINZIUQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
GetWork declare in which file?? |
Dart has recently added async callback support for FFI. There aren't much instructions of how to get it done though.
It would be great if you could give us an example code which could get us started on async calls to golang and callbacks from go to dart using FFI.
I had appreciate any sort of help.
The text was updated successfully, but these errors were encountered: