首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何创建一个指向接受dart:ffi中字符串的dart函数的指针?

如何创建一个指向接受dart:ffi中字符串的dart函数的指针?
EN

Stack Overflow用户
提问于 2022-11-27 13:26:12
回答 1查看 55关注 0票数 0

我想在dart中创建与这个C函数的绑定,这个C函数接受一个名为progress_monitor的函数指针

代码语言:javascript
运行
复制
FFI_PLUGIN_EXPORT void* magickSetProgressMonitor(..., const void* progress_monitor,...);

其中progress_monitor是一个函数指针:

代码语言:javascript
运行
复制
typedef bool(*MagickProgressMonitor)(const char *,const long long,
    const long long,void *);

在dart中,我尝试创建如下函数指针:

代码语言:javascript
运行
复制
typedef MagickProgressMonitor = bool Function(String text, int offset, int size, List<int>? clientData);

extension _MagickProgressMonitorExtension on MagickProgressMonitor {
  /// Creates a native function pointer from this method.
  Pointer<Void> toNativeFunctionPointer() {
    return Pointer.fromFunction<Bool Function(Pointer<Char>, LongLong, LongLong, Pointer<Void>)>(this, false).cast();
  }
}

但我知道这个错误:

代码语言:javascript
运行
复制
The type 'bool Function(String, int, int, List<int>?)' must be a subtype of 'Bool Function(Pointer<Char>, LongLong, LongLong, Pointer<Void>)' for 'fromFunction'.

我有两个问题:

  1. fromFunction<???>中应该使用什么类型来删除错误?
  2. C函数的最后一个参数是一个空*指针,它可以是任何东西,现在我正在尝试将它表示为dart中的List<int>和C中的unsigned char数组,但这似乎不正确,有什么方法可以更正确地处理这个问题吗?

更新:

我打算通过这样的方式公开一个api方法来使用上面的代码:

代码语言:javascript
运行
复制
  void magickSetProgressMonitor(MagickProgressMonitor progressMonitor, [List<int>? clientData]) {
    final Pointer<UnsignedChar> clientDataPtr = clientData?.toUnsignedCharArray() ?? nullptr;
    final Pointer<Void> progressMonitorPtr = progressMonitor.toNativeFunctionPointer();
    Pointer<Void> oldMonitorPtr =
        _bindings.magickSetProgressMonitor(...,progressMonitorPtr,...);
    ...
  }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-27 15:32:32

对于"void*指针“,可以使用Pointer<Void>

请参阅下面的代码,以便进行适当的类型设置。

代码语言:javascript
运行
复制
import 'dart:ffi';

import 'package:ffi/ffi.dart';

// void* magickSetProgressMonitor(uint32_t dummy, const void* progress_monitor,...);
// we need a pair of typedefs to describe the signature on both sides
// the two typedefs will look the same if there are just pointers etc
// the differences come in parameters like integers
// this is the C signature
typedef magick_set_progress_monitor = Pointer<Void> Function(
  Uint32, // this is just here as an example to show a 32 bit unsigned
  Pointer<NativeFunction<magick_progress_monitor>>,
);
// this is the Dart signature
typedef magickSetProgressMonitor = Pointer<Void> Function(
  int, // ffi has turned the C uint type to a Dart int
  Pointer<NativeFunction<magick_progress_monitor>>,
);

void main() {
  final nativeLib = DynamicLibrary.open('mydll');
  // lookupFunction is the improved syntax for looking up functions in the lib
  // its generics are the C-style signature followed by the Dart-style
  // it returns a Function that matches the Dart-style typedef
  final mspm = nativeLib
      .lookupFunction<magick_set_progress_monitor, magickSetProgressMonitor>(
    'magickSetProgressMonitor',
  );
  
  // before calling mspm it needs the callback function, so look that up
  // this converts the Dart-style function to a pointer to a native function
  // matching the C-style typedef
  final callbackFunction = Pointer.fromFunction<magick_progress_monitor>(
    callback,
    true,
  );
  
  // and call mspm passing the (dummy, example) int and callback function
  final result = mspm(123, callbackFunction);
}

//typedef bool(*MagickProgressMonitor)(const char *,const long long,
//     const long long,void *);
// callback functions need a C-style typedef (so that FFI knows the int sizes)
typedef magick_progress_monitor = Bool Function(
  Pointer<Utf8>, // the documentation says this is a string, so use Utf8
  LongLong,
  LongLong,
  Pointer<Void>,
);

bool callback(
  Pointer<Utf8> t,
  int offset,
  int extent,
  Pointer<Void> client_data,
) {
  final text = t.toDartString(); // convert the Pointer<Utf8> to Dart string
  // do something here with the values - probably call a Dart function provided by the user
  return true;
}

在编辑和问题之后进行更新。

你对回调没有选择余地。它的类型胡枝子必须与C代码期望调用的C类型胡枝子子完全匹配。您不应该向用户公开Pointer类型是正确的,所以您应该将回调函数保留在代码中,在那里转换原因字符串,然后使用Dart字符串调用用户的函数。

最后,同样明显的是,这是行不通的。顾名思义,这是一个回调函数,它被某个后台进程从主Dart线程中删除。C->Dart回调功能仅限于作为Dart>C->Dart调用的一部分立即进行的回调。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74590409

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档