【问题标题】:string to char* marshaling字符串到 char* 编组
【发布时间】:2008-11-06 19:20:21
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

    标签: .net c++ managed-c++


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        问题在于 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

        【讨论】:

          猜你喜欢
          • 2021-10-05
          • 1970-01-01
          • 2017-06-15
          • 1970-01-01
          • 2021-03-15
          • 1970-01-01
          • 2021-09-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多