我正在使用 C++/CLI,我想WNetAddConnection2
从 Windows Networking 调用该函数。
首先,我知道 C++/CLI 不是我工作的首选语言,但我现在无法更改它,例如改用 C#。
现在的问题是,这个函数需要 wchar_t*,所以我需要将 System::String^ 转换为 wchar_t*。
解决方案 1):使用pin_ptr
和PtrToSTringChars
从vcclr.h
解决方案 2):使用StringToHGlobalUni
. (标题提到StringHToGlobalAnsi
是因为更多的人正在搜索它,所以他们可能会找到这篇文章并且它的答案更快)。
我发现这两种解决方案都有效。但是#1并非如此。我已将 WNet 函数放入CWNetShare
具有以下构造函数的 ref 类中:
CWNetShare::CWNetShare (String^ i_sLocalDrive, ...) {
pin_ptr<const wchar_t> wszTemp;
wszTemp = PtrToStringChars(i_sLocalDrive);
m_wszLocalDrive = const_cast<wchar_t*>(wszTemp);
其中m_wszLocalDrive
是 type 的私有CWNetShare
成员wchar_t*
。
真正的问题:m_oWNetShare = gcnew CWNetShare
从 Winform 类构造函数(我知道,C++/CLI 和 Winforms ......)调用构造函数时,一切似乎都很好。字符串i_sLocalDrive
和其他字符串已正确转换和分配。但是m_oWNetShare
稍后访问时,所有 m_wsz... 变量中的值都会丢失。看起来对象被 GC 移动了。
因此我做了一个测试:
ref class CManaged {
public:
wchar_t* m_wszNothing;
wchar_t* m_wszPinned;
wchar_t* m_wszMarshal;
System::String^ m_sTest;
CManaged ()
{
m_sTest = "Hello";
m_wszNothing = L"Test";
pin_ptr<const wchar_t> wszTemp;
wszTemp = PtrToStringChars(m_sTest);
m_wszPinned = const_cast<wchar_t*>(wszTemp);
m_wszMarshal = static_cast<wchar_t*>(System::Runtime::InteropServices::Marshal::StringToHGlobalUni (m_sTest).ToPointer());
}
};
m_oManaged = gcnew CManaged;
再次在其构造函数中添加一个 winform 。以后访问m_oManaged的时候,如果m_oManaged没有被移动,m_wszPinned
就可以了。
但是在GCing之后,它显示出胡说八道。但是 m_wsznothing 保持它的价值,所以这不是问题wchar_t*
,而是 pin_ptr 的问题。的地址m_oManaged
变了,但是地址m_wszPinned
还是一样的,那为什么值会丢失呢?
这里出了什么问题?
那么 pin_ptr 和 PtrToSTringChars 还有用吗?
我现在正在使用编组,这很有效。