Llamar al código Go desde Dart usando cgo y Dart FFI con un ejemplo simple

La motivación clave para escribir este artículo es el hecho de una gran falta de información (especialmente en la comunidad de habla rusa) sobre el uso de cgo y Dart FFI para llamar al código Go desde el lenguaje Dart.





El idioma Dart, a pesar de su creciente popularidad, por el momento todavía no tiene la misma gran comunidad que el idioma Go. Dart está orientado a realizar otras tareas, por lo que a veces no contiene las implementaciones y la funcionalidad que Go ya tiene.





Si puede evitar exportar el código go a Dart (por ejemplo, exportar una biblioteca lista para usar), es mejor aprovechar esta oportunidad y no usar cgo. Sin embargo, puede haber casos en los que destilar en código dart sea la solución óptima (por ejemplo, ya está familiarizado con Go y Dart y no desea escribir código en C, en cuyo caso tiene sentido pensar en usar cgo y Dart FFI).





En este artículo, utilizando un ejemplo simple, se mostrará cómo puede llamar al código Go desde el lenguaje Dart (por ejemplo, en las aplicaciones Flutter).





Qué necesita ser instalado:





  • Ir





  • Dardo





  • Editor de texto / IDE (usaré VSCode, ya que es el entorno más popular entre la comunidad de Dart and Go, también se instalarán complementos especiales para admitir los idiomas Go y Flutter)





Paso 1: cree una aplicación de consola de Dart en blanco

Command Palette F1 Dart, Console Application ( , cgo Flutter Dart).





, cgo_dartffi_helloworld, . ( Dart, ffi pubspec.yaml ).





.





2 - ffi yaml

ffi yaml go dart.





name: cgo_dartffi_helloworld
description: A sample command-line application.
version: 1.0.0

environment:
  sdk: '>=2.12.0 <3.0.0'

dependencies:
  path: ^1.8.0
  ffi: ^0.1.3

dev_dependencies:
  pedantic: ^1.10.0
  test: ^1.16.0
      
      



3 - .go

go, ( , lib.go) Dart. - HelloFromGo().





// filename: lib.go
package main

import "C"

//export HelloFromGo
func HelloFromGo() *C.char {
	message := "Hello to dart lang from go"
	return C.CString(message)
}

func main() {}

      
      



cgo , . cgo (, ), ( export). cgo https://golang.org/cmd/cgo/, .





4 - go

:





go build -buildmode=c-shared -o lib.a lib.go
      
      



lib.a ( c ). ( , go, go, cgo).





5 -

:





:





  • pubspec.yaml





  • lib.h, lib.a lib.go





  • bin dart ( )





6 - cgo Dart

( ) . ( ), .





  • 6.1 - bin/cgo_dartffi_helloworld.dart





  • 6.2 - ( ffi utf8 )





import 'dart:ffi' as ffi;
import 'package:ffi/src/utf8.dart';
      
      



  • 6.3 -






final dylib = ffi.DynamicLibrary.open('lib.a');

      
      



  • 6.4 - dart





typedef HelloFromGo = ffi.Pointer<Utf8> Function();
typedef HelloFromGoFunc = ffi.Pointer<Utf8> Function();
final HelloFromGo _finalFunction = dylib
    .lookup<ffi.NativeFunction<HelloFromGoFunc>>('HelloFromGo')
    .asFunction();
      
      



  • 6.5 - ( , .toDartString C Dart):





void main() {
  print(_finalFunction().toDartString());
}
      
      



go, string Dart.





Además, al escribir sus funciones, debe tener en cuenta que los formatos de datos en los lenguajes Go, C y Dart pueden diferir (y esto sucede a menudo), lo que lleva a la necesidad de utilizar varias conversiones en el código go / dart. lateral, para obtener más detalles, consulte los siguientes enlaces:





Código completo de Dart:





import 'dart:ffi' as ffi;
import 'package:ffi/src/utf8.dart';

final dylib = ffi.DynamicLibrary.open('lib.a');

typedef HelloFromGo = ffi.Pointer<Utf8> Function();
typedef HelloFromGoFunc = ffi.Pointer<Utf8> Function();
final HelloFromGo _finalFunction = dylib
    .lookup<ffi.NativeFunction<HelloFromGoFunc>>('HelloFromGo')
    .asFunction();

void main() {
  print(_finalFunction().toDartString());
}

      
      



Si necesita pasar parámetros a la función llamada, puede usar punteros y declararlos en la función llamada, por ejemplo:





typedef GetHash = Pointer<Utf8> Function(Pointer<Utf8> str);
typedef GetHashFunc = Pointer<Utf8> Function(Pointer<Utf8> str);
final GetHash _getHashGoFunction =
    _lib.lookup<NativeFunction<GetHashFunc>>('GetHash').asFunction();
      
      



Lo principal que debe recordar es que debe verificar los formatos de los datos transmitidos.








All Articles