我想在dart中创建与这个C函数的绑定,这个C函数接受一个名为progress_monitor
的函数指针
FFI_PLUGIN_EXPORT void* magickSetProgressMonitor(..., const void* progress_monitor,...);
其中progress_monitor
是一个函数指针:
typedef bool(*MagickProgressMonitor)(const char *,const long long,
const long long,void *);
在dart中,我尝试创建如下函数指针:
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();
}
}
但我知道这个错误:
The type 'bool Function(String, int, int, List<int>?)' must be a subtype of 'Bool Function(Pointer<Char>, LongLong, LongLong, Pointer<Void>)' for 'fromFunction'.
我有两个问题:
fromFunction<???>
中应该使用什么类型来删除错误?List<int>
和C中的unsigned char
数组,但这似乎不正确,有什么方法可以更正确地处理这个问题吗?更新:
我打算通过这样的方式公开一个api方法来使用上面的代码:
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,...);
...
}
发布于 2022-11-27 15:32:32
对于"void*指针“,可以使用Pointer<Void>
。
请参阅下面的代码,以便进行适当的类型设置。
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调用的一部分立即进行的回调。
https://stackoverflow.com/questions/74590409
复制相似问题