从 C++ 传递函数指针以由 C# 调用 - 函数参数包括宽字符字符串 (LPCWSTR)
Posted
技术标签:
【中文标题】从 C++ 传递函数指针以由 C# 调用 - 函数参数包括宽字符字符串 (LPCWSTR)【英文标题】:Pass a function pointer from C++ to be called by C# - Arguments of functions include a wide char string (LPCWSTR) 【发布时间】:2011-09-11 01:19:14 【问题描述】:我正在编写一个供本地 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。方法需要同步调用。
【问题讨论】:
【参考方案1】: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);
【讨论】:
+1 出于好奇,有没有办法像使用 DLLImport 一样声明代表拥有Charset=Charset.Unicode
?
嗨,科里。非常感谢。你的回答实际上解决了我的问题。如何实现以下第二个要求:delegate void MyDelegate([MarshalAs(UnmanagedType.LPWStr)] string foo, out string val1, out int val2);换句话说,C# 调用回调,给出一个字符串参数,而在 C++ 中,基于该字符串参数,需要将 val1 和 val2 传递回 C#
@Anil:对于 p/invoke 中的LPSTR
和LPWSTR
输出参数,请使用StringBuilder
。
嗨,Ben,你能像 Cory 一样提供一个例子吗?我是 C# 和 C++/CLI 世界的新手。
@David:是的,确实有,看我的回答。 :-)【参考方案2】:
如果您想使用 CharSet
或其他什么,请参阅鲜为人知的 UnmanagedFunctionPointer
属性,它类似于代表的 DllImport
。
【讨论】:
以上是关于从 C++ 传递函数指针以由 C# 调用 - 函数参数包括宽字符字符串 (LPCWSTR)的主要内容,如果未能解决你的问题,请参考以下文章
将 C++ 结构指针从 Perl 传递给任意 dll 函数调用
C# 调用C++ DLL,而c++函数的有一个参数需要是null,该怎么传递?