Domanda

Ho scritto una classe C ++ gestita che ha la seguente funzione:

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

Come puoi vedere, questo è un metodo semplice per copiare la stringa gestita dell'ultimo errore nel mondo non gestito ( char * ).

Dalla mia classe non gestita chiamo il metodo in questo modo:

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

Inserire un breakpoint nel metodo C ++ gestito mostra che la stringa è stata tradotta correttamente nel char * . Tuttavia, una volta tornato alla classe non gestita, il contenuto di err [1000] viene perso ed è di nuovo vuoto.

È stato utile?

Soluzione

Stai assegnando il valore del parametro passato (strErrorMessage) invece di copiare a quell'indirizzo il contenuto del buffer restituito dal Maresciallo :: StringToHGlobalAnsi.

Un'implementazione corretta dovrebbe essere:

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

La lunghezza è la dimensione del buffer passato.

strncpy () copierà al massimo len byte. Se non vi è alcun byte null tra i primi n byte di str , la stringa di destinazione non verrà terminata con null. Per questo motivo forziamo lo '\ 0' nell'ultimo byte del buffer.

Altri suggerimenti

Usiamo la seguente classe C ++ per fare le conversioni per noi e funziona benissimo. Dovresti essere in grado di modificare il tuo metodo per usarlo.

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

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

Il problema è che StringToHGlobalAnsi crea una nuova memoria non aggiustata e non copia nella memoria che intendevi usare che hai assegnato in strErrorMessage.
Per risolvere questo problema dovresti fare qualcosa del tipo:

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

E l'uso dovrebbe apparire come:

char* err;
GetLastError(&err);

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

per ulteriori informazioni consulta questo msdn articolo

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top