Skip to content

Instantly share code, notes, and snippets.

@sjindel-google
Last active May 19, 2023 04:46
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sjindel-google/b88c964eb260e09280e588c41c6af3e5 to your computer and use it in GitHub Desktop.
Save sjindel-google/b88c964eb260e09280e588c41c6af3e5 to your computer and use it in GitHub Desktop.
Passing strings between Go and Dart (via FFI)
go build -o godart.so -buildmode=c-shared
dart godart.dart
import "dart:ffi";
import "dart:convert";
import 'package:ffi/ffi.dart';
class GoString extends Struct {
Pointer<Uint8> string;
@IntPtr()
int length;
String toString() {
List<int> units = [];
for (int i = 0; i < length; ++i) {
units.add(string.elementAt(i).value);
}
return Utf8Decoder().convert(units);
}
static Pointer<GoString> fromString(String string) {
List<int> units = Utf8Encoder().convert(string);
final ptr = allocate<Uint8>(count: units.length);
for (int i = 0; i < units.length; ++i) {
ptr.elementAt(i).value = units[i];
}
final GoString str = allocate<GoString>().ref;
str.length = units.length;
str.string = ptr;
return str.addressOf;
}
}
typedef logType = Void Function(Pointer<GoString>);
typedef GoLog = void Function(Pointer<GoString>);
main() {
final lib = DynamicLibrary.open("./godart.so");
final GoLog goLog = lib.lookup<NativeFunction<logType>>("Go_Log").asFunction();
final Pointer<GoString> message = GoString.fromString("Hello, Go!");
goLog(message);
free(message);
}
import "dart:ffi";
import "dart:convert";
import 'package:ffi/ffi.dart';
class GoString extends Struct {
Pointer<Uint8> string;
@IntPtr()
int length;
String toString() {
List<int> units = [];
for (int i = 0; i < length; ++i) {
units.add(string.elementAt(i).value);
}
return Utf8Decoder().convert(units);
}
static Pointer<GoString> fromString(String string) {
List<int> units = Utf8Encoder().convert(string);
final ptr = allocate<Uint8>(count: units.length);
for (int i = 0; i < units.length; ++i) {
ptr.elementAt(i).value = units[i];
}
final GoString str = allocate<GoString>().ref;
str.length = units.length;
str.string = ptr;
return str.addressOf;
}
}
typedef logType = Void Function(Pointer<GoString>);
typedef GoLog = void Function(Pointer<GoString>);
main() {
final lib = DynamicLibrary.open("./godart.so");
final GoLog goLog = lib.lookup<NativeFunction<logType>>("Go_Log").asFunction();
final Pointer<GoString> message = GoString.fromString("Hello, Go!");
goLog(message);
free(message);
}
@crossle
Copy link

crossle commented Jan 7, 2020

Can't compile use Dart VM version: 2.8.0-dev.0.0.flutter-2f57602411 on "macos_x64"

@sjindel-google
Copy link
Author

Several breaking changes have been made to the FFI since I wrote this, you'll have to consult the latest documentation for the FFI to get it to work.

@crossle
Copy link

crossle commented Jan 8, 2020

Dart VM version: 2.8.0-dev.0.0.flutter-bebc7d3af5 run ok

import "dart:ffi";
import "dart:convert";
import 'package:ffi/ffi.dart';

class GoString extends Struct {
  Pointer<Uint8> string;

  @IntPtr()
  int length;

  String toString() {
    List<int> units = [];
    for (int i = 0; i < length; ++i) {
      units.add(string.elementAt(i).value);
    }
    return Utf8Decoder().convert(units);
  }

  static Pointer<GoString> fromString(String string) {
    List<int> units = Utf8Encoder().convert(string);
    final ptr = allocate<Uint8>(count: units.length);
    for (int i = 0; i < units.length; ++i) {
      ptr.elementAt(i).value = units[i];
    }
    final GoString str = allocate<GoString>().ref;
    str.length = units.length;
    str.string = ptr;
    return str.addressOf;
  }
}

typedef logType = Void Function(Pointer<GoString>);
typedef GoLog = void Function(Pointer<GoString>);

main() {
  final lib = DynamicLibrary.open("./godart.so");
  final GoLog goLog = lib.lookup<NativeFunction<logType>>("Go_Log").asFunction();
  final Pointer<GoString> message = GoString.fromString("Hello, Go!");
  goLog(message);
  free(message);
}

@sjindel-google
Copy link
Author

@crossle Thanks, I've updated it!

@seddonm1
Copy link

@sjindel-google
Would you be able to demonstrate how to use async callbacks for Go like https://github.com/dart-lang/sdk/tree/master/samples/ffi/async ?

@ganeshrvel
Copy link

Would you be able to demonstrate how to use async callbacks for Go like https://github.com/dart-lang/sdk/tree/master/samples/ffi/async ?

@sjindel-google any help on this will be much appreciated.

@ganeshrvel
Copy link

ganeshrvel commented Aug 7, 2020

Anyone else who is interested in using Dart FFI and Go together find it here: https://github.com/mraleph/go_dart_ffi_example

@bss03arg
Copy link

bss03arg commented May 1, 2021

dart:ffi api upgraded, the code works like follow:

class GoString extends Struct {
Pointer p;

@ffi.Int64()
int n;

String toString() {
List units = [];
for (int i = 0; i < n; ++i) {
units.add(p.elementAt(i).value);
}
return Utf8Decoder().convert(units);
}

static GoString fromString(String string) {
List units = Utf8Encoder().convert(string);
var ptr = calloc(units.length);
for (int i = 0; i < units.length; ++i) {
ptr.elementAt(i).value = units[i];
}
GoString str = calloc().ref;
str.n = units.length;
str.p = ptr;
return str;
}
}

typedef _c_Command = GoString Function(GoString data);
typedef _dart_Command = GoString Function(GoString data);

typedef _c_Command2 = GoString Function();
typedef _dart_Command2 = GoString Function();

thank you for the information about the go/dart!

@user1121114685
Copy link

dart:ffi api upgraded, the code works like follow:

class GoString extends Struct {
Pointer p;

@ffi.Int64()
int n;

String toString() {
List units = [];
for (int i = 0; i < n; ++i) {
units.add(p.elementAt(i).value);
}
return Utf8Decoder().convert(units);
}

static GoString fromString(String string) {
List units = Utf8Encoder().convert(string);
var ptr = calloc(units.length);
for (int i = 0; i < units.length; ++i) {
ptr.elementAt(i).value = units[i];
}
GoString str = calloc().ref;
str.n = units.length;
str.p = ptr;
return str;
}
}

typedef _c_Command = GoString Function(GoString data);
typedef _dart_Command = GoString Function(GoString data);

typedef _c_Command2 = GoString Function();
typedef _dart_Command2 = GoString Function();

thank you for the information about the go/dart!

The same does not work in the new version of ffi?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment