从 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 中的LPSTRLPWSTR 输出参数,请使用StringBuilder 嗨,Ben,你能像 Cory 一样提供一个例子吗?我是 C# 和 C++/CLI 世界的新手。 @David:是的,确实有,看我的回答。 :-)【参考方案2】:

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

【讨论】:

以上是关于从 C++ 传递函数指针以由 C# 调用 - 函数参数包括宽字符字符串 (LPCWSTR)的主要内容,如果未能解决你的问题,请参考以下文章

从 C# 调用 C 函数,传递包含指针的结构

将 C++ 结构指针从 Perl 传递给任意 dll 函数调用

C# 调用C++ DLL,而c++函数的有一个参数需要是null,该怎么传递?

C#调用C++的dll库怎么传递结构体中不定长度的char数组

从 C# 到 C++ 的调用无法正确传递参数

c#调用c++的DLL,接口函数参数有函数指针,在线等解决办法