C# P/Invoke-将委托封送为函数指针+;空虚*

C# P/Invoke-将委托封送为函数指针+;空虚*,c#,pinvoke,C#,Pinvoke,C中一个相当常见的习惯用法是,函数使用多态闭包将其表示为两个参数,一个函数指针和一个空指针(作为参数之一传递给函数指针) 来自图书馆的一个例子: 从概念上讲,函数指针加上void指针表示与C#(闭包)中的委托相同的东西。在进行这种p/Invoke调用时,有没有一种好的、规范的方法来封送委托 在进行这种p/Invoke调用时,是否有一种好的、规范的方法来封送委托 您不需要使用void*参数,因为C#委托是一个闭包。将IntPtr.Zero作为钩子值传递。您的C#委托仍然需要接受void*参数,但它

C中一个相当常见的习惯用法是,函数使用多态闭包将其表示为两个参数,一个函数指针和一个空指针(作为参数之一传递给函数指针)

来自图书馆的一个例子:

从概念上讲,函数指针加上void指针表示与C#(闭包)中的委托相同的东西。在进行这种p/Invoke调用时,有没有一种好的、规范的方法来封送委托

在进行这种p/Invoke调用时,是否有一种好的、规范的方法来封送委托


您不需要使用
void*
参数,因为C#委托是一个闭包。将
IntPtr.Zero
作为钩子值传递。您的C#委托仍然需要接受
void*
参数,但它可以忽略它,因为它不需要它。

您实际上可以将委托从C#传递到C函数指针。您应该用
[UnmanagedFunctionPointer]
属性修饰此委托。这就是我们包装接受函数指针的C方法的方式:

C方法:

__declspec(dllexport) globle int EnvAddRouterEx(int (*queryFunction)(void*, char*))
p\Invoke方法:

[DllImport(clipsDllLocation, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern int EnvAddRouterEx(ClipsRouterQueryFunctionDelegate queryFunction);
p\Invoke委托:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int ClipsRouterQueryFunctionDelegate(IntPtr theEnv, string logicalName);

其他答案是正确的,但是,我只想附加一些C#9信息:

现在可以按如下方式在C#中使用函数指针(需要启用
safe
):

< > <代码> MyLoabl,DLL的实例C++可以是:

extern "C" __declspec(dllexport) int CallMyCallback(
    int (*callback)(int, int),
    int arg1,
    int arg2)
{
    return callback(arg1, arg2);
}
CallMyCallback
可以按如下方式使用(来自C#):


注意:此语言功能不能用于lambda表达式或非静态方法(实例方法需要传递一个隐式
This
-指针)



官方文档还不存在,但你可以看看C#9 GitHub问题/跟踪器:

谢谢。我已经有一段时间没有使用.NET了。我想这意味着全局内存中有某种垫片,可以将委托调整为纯函数指针?正确。封送框架在运行期间生成代码正在处理包含闭包信息的封送处理。请小心,保持委托对象处于活动状态是您的工作。请将其存储在静态变量中,以便不能过早地对其进行垃圾收集。只有在确定C代码无法再进行回调时,才将变量设置回null。
static int add(int a, int b) => a + b;

delegate*<int, int, int> pointer = &add;
int result = add(40, 2);
[DllImport("my_library.dll")]
static extern int CallMyCallback(delegate*<int, int, int> callback, int arg1, int arg2);
extern "C" __declspec(dllexport) int CallMyCallback(
    int (*callback)(int, int),
    int arg1,
    int arg2)
{
    return callback(arg1, arg2);
}
static int multiply(int a, int b) => a * b;

int result = CallMyCallback(&multiply, -12, 7);