2008-11-06 115 views
3

我寫具有以下功能的託管C++類:字符串爲char *編組

void EndPointsMappingWrapper::GetLastError(char* strErrorMessage) 
{ 
    strErrorMessage = (char*) Marshal::StringToHGlobalAnsi(_managedObject->GetLastError()).ToPointer(); 
} 

正如你可以看到,這是一個簡單的方法來最後一個錯誤的託管字符串複製到不可控制的世界(char*)。

從我的非託管類我把這樣的方法:

char err[1000]; 
ofer->GetLastError(err); 

在託管C++方法把一個斷點顯示,字符串被成功地轉化爲char*。但是,一旦我回到非託管類,err[1000]的內容會丟失,並且會再次爲空。

回答

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'。

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); 
} 
0

的問題是,StringToHGlobalAnsi創建一個新的unmanged內存,並且不復制到存儲你打算用你指定進入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