Motivasi utama untuk menulis artikel ini adalah kurangnya informasi yang kuat (terutama di komunitas berbahasa Rusia) tentang penggunaan cgo dan Dart FFI untuk memanggil kode Go dari bahasa Dart.
Bahasa Dart, meskipun popularitasnya meningkat, saat ini masih belum memiliki komunitas besar yang sama dengan bahasa Go. Dart diarahkan untuk melakukan tugas lain, sehingga terkadang tidak berisi implementasi dan fungsionalitas yang sudah dimiliki Go.
Jika Anda dapat menghindari mengekspor kode go ke Dart (misalnya, mengekspor perpustakaan yang sudah jadi), maka lebih baik menggunakan kesempatan ini dan tidak menggunakan cgo. Namun, mungkin ada kasus ketika penyulingan masuk ke kode dart adalah solusi optimal (misalnya, Anda sudah terbiasa dengan Go dan Dart, dan tidak ingin menulis kode dalam C, dalam hal ini masuk akal untuk berpikir tentang menggunakan cgo dan Dart FFI).
Dalam artikel ini, menggunakan contoh sederhana, akan ditunjukkan bagaimana Anda dapat memanggil kode Go dari bahasa Dart (misalnya, dalam aplikasi Flutter).
Apa yang perlu diinstal:
Pergilah
Anak panah
Editor teks / IDE (Saya akan menggunakan VSCode, karena ini adalah lingkungan paling populer di antara komunitas Dart dan Go, plugin khusus juga akan dipasang untuk mendukung bahasa Go dan Flutter)
Langkah 1 - Buat Aplikasi Konsol Dart Kosong
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.
Selanjutnya, saat menulis fungsi Anda, Anda harus mempertimbangkan bahwa format data dalam bahasa Go, C, dan Dart mungkin berbeda (dan ini sering terjadi), yang mengarah pada kebutuhan untuk menggunakan berbagai konversi saat bepergian / kode dart samping, untuk lebih jelasnya, lihat tautan berikut:
Kode Dart lengkap:
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());
}
Jika Anda perlu meneruskan parameter ke fungsi yang dipanggil, Anda dapat menggunakan pointer dan mendeklarasikannya dalam fungsi yang dipanggil, misalnya:
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();
Hal utama yang perlu diingat adalah Anda perlu memeriksa format data yang dikirimkan.