从 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 Union(C) 与包含 C# 中的数组的结构