将回调参数从 C# 传递到非托管 C++

var*_*ard 4 c# c++ marshalling

我有一些非托管的 C++ 动态库和 C# GUI 应用程序,正在使用它。我想通过一些库提供的方法中的参数传递回调。是否可以将回调传递给 C# 中的非托管 C++ 方法。

// unmanaged C++
typedef uint8_t (__stdcall *SomeCallback)();

MYDLL_API uint8_t someMethod(SomeCallback cb);
Run Code Online (Sandbox Code Playgroud)

我正在尝试以这种方式使用库:

// C# part
public delegate Byte SomeDelegate();

[DllImport("mylibraryname.dll")]
public static extern Byte someMethod(ref SomeDelegate pDelegate);

// actuak callback
Byte myCallback() {
    // some code
}

...

// call unmanaged passing callback
static void Main(string[] args) {          
    someMethod(myCallback);
}
Run Code Online (Sandbox Code Playgroud)

我在编译时收到错误:

 cannot convert from 'method group' to 'ref SomeDelegate
Run Code Online (Sandbox Code Playgroud)

我的方法完全错误吗?

Ali*_*eza 6

这是因为您必须将ref修饰符放在参数之前,并强制它成为一个变量。所以:

将您更改为:

public static extern Byte someMethod([MarshalAs(UnmanagedType.FunctionPtr)] 
                            ref SomeDelegate pDelegate);
Run Code Online (Sandbox Code Playgroud)

以及您致电:

        SomeDelegate action = new SomeDelegate(myCallback);
        someMethod(ref action);
Run Code Online (Sandbox Code Playgroud)

更新:如果您想将参数传递给回调(例如 int):

public delegate Byte SomeDelegate([MarshalAs(UnmanagedType.I4)] int value);

[DllImport("mylibraryname.dll")]
public static extern Byte someMethod([MarshalAs(UnmanagedType.FunctionPtr)]
                                       ref SomeDelegate pDelegate);

Byte MyMethod([MarshalAs(UnmanagedType.I4)] int value)
{
    return (byte) (value & 0xFF);
}
Run Code Online (Sandbox Code Playgroud)

并调用:

SomeDelegate action = new SomeDelegate(MyMethod);
someMethod(ref action);
Run Code Online (Sandbox Code Playgroud)