为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用 FFI 从 Dart 调用 Go lib

如何使用 FFI 从 Dart 调用 Go lib

Go
函数式编程 2022-06-27 15:57:29
我需要在 中编写一个函数GO,将其编译为共享库,然后从Dart. 例如,要返回一个键,如下面的代码所示:package mainfunc getKey() string {    theKey := "123-456-789"    return theKey}func main() {}
查看完整描述

1 回答

?
GCT1015

TA贡献1827条经验 获得超4个赞

答案是:

第一部分GO 方面:

  1. 我们需要使函数可导出,因此名称应大写并变为GetKey()

  2. 我们需要使用cgo以便我们可以创建共享库,cgo这意味着我们需要:

2.1。利用import "C"

2.2. 将注释与函数一起使用//export GetKey

2.3. 使用C.type接口,在本例中,代替string使用C.charand C.CString,因为使用指针是更可取的方式,使用*C.char

因此,Go问题中的函数应重写为:

// filename: lib.go

package main


import "C"


//export GetKey

func GetKey() *C.char {

    theKey := "123-456-789"

    return C.CString(theKey)

}


func main() {}  

编译上述内容并将共享库创建为:

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

第二部分Dart 方面:


创建pubspec.yaml并添加到它的依赖项中ffi: ^0.1.3,所以它是:

name: dart_app

description: A new Dart application.


# The following line prevents the package from being accidentally published to

# pub.dev using `pub publish`. This is preferred for private packages.

publish_to: 'none' # Remove this line if you wish to publish to pub.dev

version: 1.0.0+1


environment:

  sdk: ">=2.7.0 <3.0.0"


dependencies:

  ffi: ^0.1.3

将生成的文件从 GO 复制lib.a到lib.hdart projetc 文件夹

创建 dart 文件来处理 FFI,您需要: 3.1. 导入ffi和utf8

3.2. 将 FFI 函数签名定义为typedef get_key_func = ffi.Pointer<Utf8> Function();


3.3. 将 Dart 函数签名定义为typedef GetKey = ffi.Pointer<Utf8> Function();


3.4. 将共享库加载为final dylib = ffi.DynamicLibrary.open('lib.a');


3.5. 将 FFI 和 Dart 函数签名映射为final GetKey getKey dylib.lookup<ffi.NativeFunction<get_key_func>>('GetKey').asFunction();


3.6. 定义一个函数来执行,并在这个函数内部执行以下操作:


3.6.1. 调用 Dart 函数并将输出分配给一个变量var addressOf = getKey();


3.6.2. 解码结果,即指针的地址,并从中获取字符串,如下所示:print(addressOf.ref.toString());


因此,Dart 代码将变为:


//file name fficheck.dart

import 'dart:ffi' as ffi; // For FFI

import 'package:ffi/ffi.dart';

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


typedef get_key_func = ffi.Pointer<Utf8> Function(); // FFI fn signature

typedef GetKey = ffi.Pointer<Utf8> Function(); // Dart fn signature

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


final GetKey getKey =

    dylib.lookup<ffi.NativeFunction<get_key_func>>('GetKey').asFunction();


void testffi() {

  print("Hi from dart");

  var addressOf = getKey();

  print(addressOf.ref.toString());

}

创建主要的 Dart 文件,并导入处理 FFI 的文件,并调用所需的函数,如下所示:

// file name lib.dart

import 'fficheck.dart';


main() {

  print("Hello, World!");

  testffi();

}

执行 dart 文件为dart main.dart

//img1.sycdn.imooc.com//62b9631400010cda12580551.jpg

快速注意,不要远离问题的范围,如果你返回一个字符串,那么如果你从代码中调用它,那么这个函数的返回值必须C在 C 代码中显式释放,但是当你从垃圾中调用它时收集器环境,Java/Kotlin 你不想担心它。

如果释放分配的缓冲区不方便,通常填充调用者提供的缓冲区:

func GetKey(buff *C.char, n int) int

如果您可以分配内存但不想处理 C 字符串,则可以将缓冲区插入指针并返回大小。

func GetKey(buff **C.char) int


查看完整回答
反对 回复 2022-06-27
  • 1 回答
  • 0 关注
  • 182 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号