我编写了一个托管C ++类,它具有以下功能:
void EndPointsMappingWrapper::GetLastError(char* strErrorMessage)
{
strErrorMessage = (char*) Marshal::StringToHGlobalAnsi(_managedObject->GetLastError()).ToPointer();
}
如您所见,这是将上一个错误的托管字符串复制到非托管世界(char*
)的简单方法。
从我的非托管类中,我调用这样的方法:
char err[1000];
ofer->GetLastError(err);
在托管C ++方法上放置一个断点,表明该字符串已成功转换为char*
。但是,一旦我返回到非托管类,err[1000]
的内容将丢失,并且它再次为空。
答案 0 :(得分:2)
您正在分配传递参数(strErrorMessage)的值,而不是将Marshal :: StringToHGlobalAnsi返回的缓冲区内容复制到该地址。
正确的实施应该是:
void EndPointsMappingWrapper::GetLastError(char* strErrorMessage, int len)
{ char *str = (char*) Marshal::StringToHGlobalAnsi(_managedObject->GetLastError()).ToPointer();
strncpy(strErrorMessage,str,len);
strErrorMessage[len-1] = '\0';
Marshal::FreeHGlobal(IntPtr(str));
}
长度是传递的缓冲区的大小。
strncpy()
将复制最多 len 字节。如果 str 的前n个字节中没有空字节,则目标字符串不会以空值终止。出于这个原因,我们强制缓冲区的最后一个字节中的'\ 0'。
答案 1 :(得分:0)
我们使用以下C ++类为我们进行转换,并且工作正常。您应该能够修改您的方法以使用它。
H档
public ref class ManagedStringConverter
{
public:
ManagedStringConverter( System::String^ pString );
~ManagedStringConverter();
property char* PrimitiveString
{
char* get() { return m_pString; }
}
/// <summary>
/// Converts a System::String to a char * string. You must release this with FreeString.
/// </summary>
static const char* StringToChar( System::String^ str );
/// <summary>
/// Converts a System::String to a __wchar_t * string. You must release this with FreeString.
/// </summary>
static const __wchar_t * StringToWChar( System::String^ str );
/// <summary>
/// Frees memory allocated in StringToChar()
/// </summary>
static void FreeString( const char * pszStr );
private:
char* m_pString;
};
CPP档案
ManagedStringConverter::ManagedStringConverter( System::String^ pString )
{
m_pString = const_cast<char*>( ManagedStringConverter::StringToChar( pString ) );
}
ManagedStringConverter::~ManagedStringConverter()
{
ManagedStringConverter::FreeString( m_pString );
}
// static
const char * ManagedStringConverter::StringToChar( System::String^ str )
{
IntPtr^ ip = Marshal::StringToHGlobalAnsi( str );
if ( ip != IntPtr::Zero )
{
return reinterpret_cast<const char *>( ip->ToPointer() );
}
else
{
return nullptr;
}
}
// static
const __wchar_t * ManagedStringConverter::StringToWChar( System::String^ str )
{
IntPtr^ ip = Marshal::StringToHGlobalUni( str );
if ( ip != IntPtr::Zero )
{
return reinterpret_cast<const __wchar_t *>( ip->ToPointer() );
}
else
{
return nullptr;
}
}
// static
void ManagedStringConverter::FreeString( const char * pszStr )
{
IntPtr ip = IntPtr( (void *)pszStr );
Marshal::FreeHGlobal( ip );
}
答案 2 :(得分:0)
问题是StringToHGlobalAnsi创建了一个新的无人管内存,并且不会复制到您要分配给strErrorMessage的内存中。
要解决这个问题,你应该做一些事情:
void EndPointsMappingWrapper::GetLastError(char** strErrorMessage)
{
*strErrorMessage = (char*) Marshal::StringToHGlobalAnsi(_managedObject->GetLastError()).ToPointer();
}
用法应该如下:
char* err;
GetLastError(&err);
//and here you need to free the error string memory
有关详细信息,请查看此msdn article