【发布时间】:2015-04-19 03:05:18
【问题描述】:
在 C 中,有一个函数接受指向函数的指针来执行比较:
[DllImport("mylibrary.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int set_compare(IntPtr id, MarshalAs(UnmanagedType.FunctionPtr)]CompareFunction cmp);
在 C# 中,将委托传递给 C 函数:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int CompareFunction(ref IntPtr left, ref IntPtr right);
目前,我在泛型类的构造函数中接受 Func<T,T,int> comparer 并将其转换为委托。 “mylibrary.dll”拥有数据,托管C#库知道如何将指针转换为T,然后比较Ts。
//.in ctor
CompareFunction cmpFunc = (ref IntPtr left, ref IntPtr right) => {
var l = GenericFromPointer<T>(left);
var r = GenericFromPointer<T>(right);
return comparer(l, r);
};
我还可以选择用 C 语言为 90% 以上的情况下使用的最重要的数据类型编写一个 CompareFunction,但我希望避免修改本机库。
问题是,当使用 P/Invoke 设置比较函数时,从 C 代码对该函数的每次后续调用都会产生编组开销,还是从 C 调用委托就好像它最初是用 C 编写的一样?
我想,在编译时,委托是内存中的一系列机器指令,但不明白 C 代码是否/为什么需要要求 .NET 进行实际比较,而不是仅仅执行这些指令?
我最感兴趣的是更好地了解互操作的工作原理。但是,此委托用于对大数据集进行二分搜索,如果每个后续调用作为单个 P/Invoke 都有一些开销,那么在原生 C 中重写比较器可能是一个不错的选择。
【问题讨论】:
标签: c# .net c interop unmanaged