从 C++ 到 C# 的结构中的 Marshal 回调

Posted

技术标签:

【中文标题】从 C++ 到 C# 的结构中的 Marshal 回调【英文标题】:Marshal callback in a struct from C++ to C# 【发布时间】:2019-02-26 08:38:03 【问题描述】:

我需要将有关对象的必要信息作为带有回调和其他数据的结构返回。

这就是它在 C# 端的样子:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void ChartAddDataCallback(IntPtr data, int size);

[StructLayout(LayoutKind.Sequential)]
public struct ChartAccessors

    public IntPtr HWnd;
    public ChartAddDataCallback addDataCallback;


[DllImport("CppPart.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "GetAccessors")]
public static extern ChartAccessors GetAccessors();

C++“镜像”版本如下所示:

typedef void(__cdecl *AddDataCallback) (int * data, int size);

struct ChartAccessors

    HWND m_chartHWnd;
    AddDataCallback m_addDataCallback;
;

extern "C" __declspec(dllexport) ChartAccessors GetAccessors();

用法:

static void Main(string[] args)

    ChartAccessors accessors = GetAccessors();

但是,当我启动程序时,我收到异常“方法的类型签名与 PInvoke 不兼容。” 如果我使用任何其他返回类型(如 int 或 float)而不是 struct,它就可以工作。

【问题讨论】:

怎么称呼,可以分享一下例子吗?您可以尝试修改GetAccessors(); 方法以返回IntPtr 而不是使用Marshal.PtrToStructure 方法 看看这篇文章docs.microsoft.com/en-us/dotnet/framework/interop/…也许你在C++声明中遗漏了一些东西 嗨,帕维尔,感谢您的回复。我添加了用法(这相当简单)。我试图将它作为 IntPtr 返回并将其编组到结构中,但这给了我一个致命错误。我像这样从 C++ 返回它 -> return new ChartAccessors(); 尝试检查这个线程***.com/questions/22803083/… charset 和 C/C++ 字符串可能有问题 我的程序中没有字符串 【参考方案1】:

Marshal.PtrToStructure 实际上正在解决这个问题,正如Pavel 所指出的那样。

void RegisterCallbacks(IntPtr callbackPtr)

    ChartAccessors accessors = (ChartAccessors)Marshal.PtrToStructure(callbackPtr, typeof(ChartAccessors));
    // do stuff with the struct

【讨论】:

以上是关于从 C++ 到 C# 的结构中的 Marshal 回调的主要内容,如果未能解决你的问题,请参考以下文章

注册 C# 委托给 C++ 回调,Marshal.GetFunctionPointerForDelegate 有啥作用?

通过 Marshal.GetFunctionPointerForDelegate 从本机 (C++) 线程调用托管函数 (C#)

Marshal.Sizeof() 返回意外值

Marshal Union(C) 与包含 C# 中的数组的结构

从 const char* 复制到字节数组 C++/c# interop Marshal::Copy

C#引用c++DLL结构体数组注意事项(数据发送与接收时)