Frage

Ich schrieb eine verwaltete C ++ Klasse, die die folgende Funktion hat:

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

Wie Sie sehen können, ist dies eine einfache Methode, die verwaltete Zeichenfolge des letzten Fehlers auf die nicht verwalteten Welt (char*) zu kopieren.

Aus meiner nicht verwalteten Klasse nenne ich die Methode wie folgt aus:

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

Setzen Sie einen Haltepunkt an der verwalteten C ++ Methode zeigt, dass die Zeichenfolge erfolgreich in die char* übersetzt. Aber sobald ich auf die nicht verwalteten Klasse zurückgeben, der Gehalt an err[1000] verloren und es ist wieder leer.

War es hilfreich?

Lösung

Sie werden den Wert des übergebenen Parameters (strErrorMessage) anstelle des Kopierens die Zuordnung der Inhalt des Puffers an diese Adresse zurück von Marshal :: StringToHGlobalAnsi.

Eine korrekte Implementierung sollte sein:

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

Die Länge ist die Größe des Puffers übergeben.

strncpy() wird bei dem Kopieren len Bytes. Wenn es kein Null-Byte unter den ersten n Bytes des str , wird der Ziel-String nicht null beendet werden. Aus diesem Grunde zwingen wir die ‚\ 0‘ im letzten Byte des Puffers.

Andere Tipps

Wir verwenden Sie die folgende C ++ Klasse die Konvertierungen für uns zu tun und es funktioniert gut. Sie sollten in der Lage sein, Ihre Methode zu ändern, es zu benutzen.

H Datei

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-Datei

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

Das Problem ist, dass StringToHGlobalAnsi einen neuen unmanged Speicher erzeugt und kopiert nicht in den Speicher, den Sie bestimmt, welche Sie in strErrorMessage zugewiesen zu verwenden.
Um dies zu beheben, Sie sollten etwas tun wie:

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

Und sollte die Verwendung wie folgt aussehen:

char* err;
GetLastError(&err);

//and here you need to free the error string memory

Für weitere Informationen lesen Sie in diesem Msdn Artikel

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top