字符串到 char* 封送

发布于 2024-07-08 08:13:17 字数 510 浏览 9 评论 0原文

我编写了一个托管 C++ 类,它具有以下功能:

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

如您所见,这是一个将最后一个错误的托管字符串复制到非托管世界 (char*) 的简单方法。

在我的非托管类中,我这样调用该方法:

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

在托管 C++ 方法处放置断点表明该字符串已成功转换为 char*。 但是,一旦我返回到非托管类,err[1000] 的内容就会丢失,并且再次为空。

I wrote a managed C++ class that has the following function:

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

As you can see, this is a simple method to copy the managed string of the last error to the unmanaged world (char*).

From my unmanaged class I call the method like this:

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

Putting a breakpoint at the managed C++ method shows that the string is successfully translated into the char*. However, once I return to the unmanaged class, the content of err[1000] is lost and it's empty again.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

野侃 2024-07-15 08:13:17

您正在分配传递的参数 (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”。

You are assigning the value of the passed parameter (strErrorMessage) instead of copying to that address the content of the buffer returned by Marshal::StringToHGlobalAnsi.

A correct implementation should be:

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

The length is the size of the buffer passed.

strncpy() will copy at the most len bytes. If there is no null byte among the first n bytes of the str, the destination string won't be null terminated. For that reason we force the '\0' in the last byte of the buffer.

つ低調成傷 2024-07-15 08:13:17

我们使用以下 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 );
}

We use the following C++ Class to do the conversions for us and it works fine. You should be able to modify your method to use it.

H File

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 File

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 );
}
风透绣罗衣 2024-07-15 08:13:17

问题是 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 文章

The problem is that StringToHGlobalAnsi creates a new unmanged memory and does not copy into the memory you intended to use which you assigned into strErrorMessage.
To resolve this you should do some thing like:

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

And the usage should look like:

char* err;
GetLastError(&err);

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

for more information check out this msdn article

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文