从C++传递一个函数指针,由C#调用-函数的参数包括一个宽字符串(LPCWSTR)

本文关键字:函数 调用 LPCWSTR 参数 包括一 字符串 指针 C++ 一个 | 更新日期: 2023-09-27 17:58:53

我正在编写一个C#库,供本机C++应用程序使用。我使用C++/CLI作为互操作性机制。

我需要将一个回调函数从C++传递到C#(使用C++/CLI作为中间层)。C#库需要使用宽字符的零终止字符串来调用C++函数;即回调函数的原型是

Func(LPCWSTR pszString);

还有其他参数,但它们对本次讨论来说无关紧要。

我在网上搜索了一下,找到了我可以使用的Marshal.GetDelegateForFunctionPointer方法。问题是它将System.String从C#转换为char*,而不是我想要的wchar_t*。

此外,如果可能的话,实现这个代码示例的最佳方法是什么,包括C++/CLI部分。C++/CLI dll依赖于C#dll。方法需要同步调用。

从C++传递一个函数指针,由C#调用-函数的参数包括一个宽字符串(LPCWSTR)

GetDelegateForFunctionPointer可以工作,但您需要向委托声明中的参数添加[MarshalAs(UnmanagedType.LPWStr)]属性,以便将String转换为wchar_t*:

delegate void MyDelegate([MarshalAs(UnmanagedType.LPWStr)] string foo)
IntPtr func = ...;
MyDelegate del = (MyDelegate)Marshal.GetDelegateForFunctionPointer(func,
                                 typeof(MyDelegate));

要传递可修改的字符串,请给出StringBuilder。您需要显式地为非托管函数保留空间以便使用:

delegate void MyDelegate([MarshalAs(UnmanagedType.LPWStr)] StringBuilder foo)
StringBuilder sb = new StringBuilder(64); // reserve 64 characters.
del(sb);

如果您想使用CharSet或其他什么,请参阅鲜为人知的UnmanagedFunctionPointer属性,它类似于代理的DllImport