簡単な例で cgo と Dart FFI を使用して Dart から Go コードを呼び出す

この記事を書く主な動機は、cgo と Dart FFI を使用して Dart 言語から Go コードを呼び出すことに関する情報が (特にロシア語を話すコミュニティで) 大幅に不足しているという事実です。





Dart 言語は、その人気が高まっているにもかかわらず、現時点では Go 言語と同じ大きなコミュニティを持っていません。Dart は他のタスクの実行を対象としているため、Go がすでに備えている実装や機能が含まれていない場合があります。





go コードの Dart へのエクスポート (たとえば、既製のライブラリのエクスポート) を回避できる場合は、cgo を使用せず、この機会を利用することをお勧めします。ただし、go を dart コードに絞り込むことが最適なソリューションである場合もあります (たとえば、Go と Dart に既に慣れていて、C でコードを記述したくない場合など、cgo の使用を検討するのが理にかなっていますおよびダート FFI)。





この記事では、簡単な例を使用して、Dart 言語から Go コードを呼び出す方法を示します (たとえば、Flutter アプリケーションで)。





インストールする必要があるもの:





  • 行く





  • ダーツ





  • テキスト エディター / IDE (VSCode を使用します。これは Dart および Go コミュニティの中で最も人気のある環境であるため、Go および Flutter 言語をサポートするための特別なプラグインもインストールされます)





ステップ 1 - 空の Dart コンソール アプリケーションを作成する

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.





さらに、関数を作成するときは、Go、C、および Dart 言語のデータ形式が異なる可能性があることを考慮に入れる必要があります (多くの場合、これが発生します)。詳細については、次のリンクを参照してください。





完全な 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());
}

      
      



呼び出された関数にパラメーターを渡す必要がある場合は、ポインターを使用して、呼び出された関数でそれらを宣言できます。次に例を示します。





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();
      
      



覚えておくべき主なことは、送信されたデータの形式を確認する必要があることです。








All Articles