C++/CLI 从 System::String^ 转换为 std::string

发布于 2024-07-23 22:26:22 字数 245 浏览 7 评论 0原文

有人可以发布一个简单的代码来转换

System::String^

To,

C++ std::string

即,我只想分配

String^ originalString;

To 的值,

std::string newString;

Can someone please post a simple code that would convert,

System::String^

To,

C++ std::string

I.e., I just want to assign the value of,

String^ originalString;

To,

std::string newString;

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

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

发布评论

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

评论(11

打小就很酷 2024-07-30 22:26:22

以下是我多年前为 C++/cli 项目编写的一些转换例程,它们应该仍然有效。

void StringToStlWString ( System::String const^ s, std::wstring& os)
    {
        String^ string = const_cast<String^>(s);
        const wchar_t* chars = reinterpret_cast<const wchar_t*>((Marshal::StringToHGlobalUni(string)).ToPointer());
        os = chars;
        Marshal::FreeHGlobal(IntPtr((void*)chars));

    }
    System::String^ StlWStringToString (std::wstring const& os) {
        String^ str = gcnew String(os.c_str());
        //String^ str = gcnew String("");
        return str;
    }

    System::String^ WPtrToString(wchar_t const* pData, int length) {
        if (length == 0) {
            //use null termination
            length = wcslen(pData);
            if (length == 0) {
                System::String^ ret = "";
                return ret;
            }
        }

        System::IntPtr bfr = System::IntPtr(const_cast<wchar_t*>(pData));
        System::String^ ret = System::Runtime::InteropServices::Marshal::PtrToStringUni(bfr, length);
        return ret;
    }

    void Utf8ToStlWString(char const* pUtfString, std::wstring& stlString) {
        //wchar_t* pString;
        MAKE_WIDEPTR_FROMUTF8(pString, pUtfString);
        stlString = pString;
    }

    void Utf8ToStlWStringN(char const* pUtfString, std::wstring& stlString, ULONG length) {
        //wchar_t* pString;
        MAKE_WIDEPTR_FROMUTF8N(pString, pUtfString, length);
        stlString = pString;
    }

Here are some conversion routines I wrote many years ago for a c++/cli project, they should still work.

void StringToStlWString ( System::String const^ s, std::wstring& os)
    {
        String^ string = const_cast<String^>(s);
        const wchar_t* chars = reinterpret_cast<const wchar_t*>((Marshal::StringToHGlobalUni(string)).ToPointer());
        os = chars;
        Marshal::FreeHGlobal(IntPtr((void*)chars));

    }
    System::String^ StlWStringToString (std::wstring const& os) {
        String^ str = gcnew String(os.c_str());
        //String^ str = gcnew String("");
        return str;
    }

    System::String^ WPtrToString(wchar_t const* pData, int length) {
        if (length == 0) {
            //use null termination
            length = wcslen(pData);
            if (length == 0) {
                System::String^ ret = "";
                return ret;
            }
        }

        System::IntPtr bfr = System::IntPtr(const_cast<wchar_t*>(pData));
        System::String^ ret = System::Runtime::InteropServices::Marshal::PtrToStringUni(bfr, length);
        return ret;
    }

    void Utf8ToStlWString(char const* pUtfString, std::wstring& stlString) {
        //wchar_t* pString;
        MAKE_WIDEPTR_FROMUTF8(pString, pUtfString);
        stlString = pString;
    }

    void Utf8ToStlWStringN(char const* pUtfString, std::wstring& stlString, ULONG length) {
        //wchar_t* pString;
        MAKE_WIDEPTR_FROMUTF8N(pString, pUtfString, length);
        stlString = pString;
    }
零時差 2024-07-30 22:26:22

我发现从 String^ 获取 std::string 的简单方法是使用 sprintf()。

char cStr[50] = { 0 };
String^ clrString = "Hello";
if (clrString->Length < sizeof(cStr))
  sprintf(cStr, "%s", clrString);
std::string stlString(cStr);

无需调用 Marshal 函数!

更新 感谢 Eric,我修改了示例代码来检查输入字符串的大小,以防止缓冲区溢出。

I found an easy way to get a std::string from a String^ is to use sprintf().

char cStr[50] = { 0 };
String^ clrString = "Hello";
if (clrString->Length < sizeof(cStr))
  sprintf(cStr, "%s", clrString);
std::string stlString(cStr);

No need to call the Marshal functions!

UPDATE Thanks to Eric, I've modified the sample code to check for the size of the input string to prevent buffer overflow.

落叶缤纷 2024-07-30 22:26:22

查看 System::Runtime::InteropServices::Marshal::StringToCoTaskMemUni() 及其朋友。

抱歉,现在无法发布代码; 我这台机器上没有 VS,无法在发布之前检查它的编译情况。

Check out System::Runtime::InteropServices::Marshal::StringToCoTaskMemUni() and its friends.

Sorry can't post code now; I don't have VS on this machine to check it compiles before posting.

七色彩虹 2024-07-30 22:26:22

这对我有用:

#include <stdlib.h>
#include <string.h>
#include <msclr\marshal_cppstd.h>
//..
using namespace msclr::interop;
//..
System::String^ clrString = (TextoDeBoton);
std::string stdString = marshal_as<std::string>(clrString); //String^ to std
//System::String^ myString = marshal_as<System::String^>(MyBasicStirng); //std to String^
prueba.CopyInfo(stdString); //MyMethod
//..
//Where: String^ = TextoDeBoton;
//and stdString is a "normal" string;

This worked for me:

#include <stdlib.h>
#include <string.h>
#include <msclr\marshal_cppstd.h>
//..
using namespace msclr::interop;
//..
System::String^ clrString = (TextoDeBoton);
std::string stdString = marshal_as<std::string>(clrString); //String^ to std
//System::String^ myString = marshal_as<System::String^>(MyBasicStirng); //std to String^
prueba.CopyInfo(stdString); //MyMethod
//..
//Where: String^ = TextoDeBoton;
//and stdString is a "normal" string;
離人涙 2024-07-30 22:26:22

不要自己动手,使用这些方便(且可扩展)的包装器由微软提供。

例如:

#include <msclr\marshal_cppstd.h>

System::String^ managed = "test";
std::string unmanaged = msclr::interop::marshal_as<std::string>(managed);

Don't roll your own, use these handy (and extensible) wrappers provided by Microsoft.

For example:

#include <msclr\marshal_cppstd.h>

System::String^ managed = "test";
std::string unmanaged = msclr::interop::marshal_as<std::string>(managed);
饭团 2024-07-30 22:26:22

您可以轻松地按如下方式执行此操作

#include <msclr/marshal_cppstd.h>

System::String^ xyz="Hi boys"; 

std::string converted_xyz=msclr::interop::marshal_as< std::string >( xyz);

You can easily do this as follows

#include <msclr/marshal_cppstd.h>

System::String^ xyz="Hi boys"; 

std::string converted_xyz=msclr::interop::marshal_as< std::string >( xyz);
虚拟世界 2024-07-30 22:26:22

C# 使用 UTF16 格式作为字符串。
因此,除了转换类型之外,您还应该注意字符串的实际格式。

编译多字节字符集时,Visual Studio 和 Win API 假定为 UTF8(实际上 Windows 编码为 Windows-28591 )。
针对Unicode 字符集进行编译时,Visual studio 和 Win API 假定为 UTF16。

因此,您还必须将字符串从 UTF16 格式转换为 UTF8 格式,而不仅仅是转换为 std::string。
当使用多字符格式(例如某些非拉丁语言)时,这将变得必要。

这个想法是决定 std::wstring 始终 代表 UTF16
std::string always 代表UTF8

这不是由编译器强制执行的,它更像是一个好的策略。

#include "stdafx.h"
#include <string>
#include <codecvt>
#include <msclr\marshal_cppstd.h>

using namespace System;

int main(array<System::String ^> ^args)
{
    System::String^ managedString = "test";

    msclr::interop::marshal_context context;

    //Actual format is UTF16, so represent as wstring
    std::wstring utf16NativeString = context.marshal_as<std::wstring>(managedString); 

    //C++11 format converter
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;

    //convert to UTF8 and std::string
    std::string utf8NativeString = convert.to_bytes(utf16NativeString);

    return 0;
}

或者使用更紧凑的语法:

int main(array<System::String ^> ^args)
{
    System::String^ managedString = "test";

    msclr::interop::marshal_context context;
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;

    std::string utf8NativeString = convert.to_bytes(context.marshal_as<std::wstring>(managedString));

    return 0;
}

C# uses the UTF16 format for its strings.
So, besides just converting the types, you should also be conscious about the string's actual format.

When compiling for Multi-byte Character set Visual Studio and the Win API assumes UTF8 (Actually windows encoding which is Windows-28591 ).
When compiling for Unicode Character set Visual studio and the Win API assume UTF16.

So, you must convert the string from UTF16 to UTF8 format as well, and not just convert to std::string.
This will become necessary when working with multi-character formats like some non-latin languages.

The idea is to decide that std::wstring always represents UTF16.
And std::string always represents UTF8.

This isn't enforced by the compiler, it's more of a good policy to have.

#include "stdafx.h"
#include <string>
#include <codecvt>
#include <msclr\marshal_cppstd.h>

using namespace System;

int main(array<System::String ^> ^args)
{
    System::String^ managedString = "test";

    msclr::interop::marshal_context context;

    //Actual format is UTF16, so represent as wstring
    std::wstring utf16NativeString = context.marshal_as<std::wstring>(managedString); 

    //C++11 format converter
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;

    //convert to UTF8 and std::string
    std::string utf8NativeString = convert.to_bytes(utf16NativeString);

    return 0;
}

Or have it in a more compact syntax:

int main(array<System::String ^> ^args)
{
    System::String^ managedString = "test";

    msclr::interop::marshal_context context;
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;

    std::string utf8NativeString = convert.to_bytes(context.marshal_as<std::wstring>(managedString));

    return 0;
}
旧人哭 2024-07-30 22:26:22

我喜欢远离编组员。

Using CString newString(originalString);

对我来说看起来更干净、更快。 无需担心创建和删除上下文。

I like to stay away from the marshaller.

Using CString newString(originalString);

Seems much cleaner and faster to me. No need to worry about creating and deleting a context.

世俗缘 2024-07-30 22:26:22

// 我使用VS2012编写了以下代码--convert_system_string to Standard_Sting

        #include "stdafx.h"
        #include <iostream>
        #include <string> 

        using namespace System;
        using namespace Runtime::InteropServices; 


        void MarshalString ( String^ s, std::string& outputstring )
        {  
           const char* kPtoC =  (const char*) (Marshal::StringToHGlobalAnsi(s)).ToPointer();                                                        
           outputstring = kPtoC;  
           Marshal::FreeHGlobal(IntPtr((void*)kPtoC));  
        }   

        int _tmain(int argc, _TCHAR* argv[])
        {
             std::string strNativeString;  
             String ^ strManagedString = "Temp";

             MarshalString(strManagedString, strNativeString);  
             std::cout << strNativeString << std::endl; 

             return 0;
        }

// I used VS2012 to write below code-- convert_system_string to Standard_Sting

        #include "stdafx.h"
        #include <iostream>
        #include <string> 

        using namespace System;
        using namespace Runtime::InteropServices; 


        void MarshalString ( String^ s, std::string& outputstring )
        {  
           const char* kPtoC =  (const char*) (Marshal::StringToHGlobalAnsi(s)).ToPointer();                                                        
           outputstring = kPtoC;  
           Marshal::FreeHGlobal(IntPtr((void*)kPtoC));  
        }   

        int _tmain(int argc, _TCHAR* argv[])
        {
             std::string strNativeString;  
             String ^ strManagedString = "Temp";

             MarshalString(strManagedString, strNativeString);  
             std::cout << strNativeString << std::endl; 

             return 0;
        }
一杯敬自由 2024-07-30 22:26:22

我花了几个小时尝试将 Windows 表单列表框 ToString 值转换为标准字符串,以便我可以将它与 fstream 一起使用以输出到 txt 文件。 我的 Visual Studio 没有附带 marshal 头文件,我发现有几个答案说可以使用这些头文件。 经过这么多次尝试和错误,我终于找到了仅使用 System::Runtime::InteropServices: 问题的解决方案:

void MarshalString ( String ^ s, string& os ) {
   using namespace Runtime::InteropServices;
   const char* chars = 
      (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
   os = chars;
   Marshal::FreeHGlobal(IntPtr((void*)chars));
}

//this is the code to use the function:
scheduleBox->SetSelected(0,true);
string a = "test";
String ^ c = gcnew String(scheduleBox->SelectedItem->ToString());
MarshalString(c, a);
filestream << a;

下面是包含示例的 MSDN 页面:
http://msdn.microsoft.com/en-us/library/1b4az623 (v=vs.80).aspx

我知道这是一个非常简单的解决方案,但这花了我几个小时的时间进行故障排除并访问多个论坛,最终找到了有效的解决方案。

I spent hours trying to convert a windows form listbox ToString value to a standard string so that I could use it with fstream to output to a txt file. My Visual Studio didn't come with marshal header files which several answers I found said to use. After so much trial and error I finally found a solution to the problem that just uses System::Runtime::InteropServices:

void MarshalString ( String ^ s, string& os ) {
   using namespace Runtime::InteropServices;
   const char* chars = 
      (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
   os = chars;
   Marshal::FreeHGlobal(IntPtr((void*)chars));
}

//this is the code to use the function:
scheduleBox->SetSelected(0,true);
string a = "test";
String ^ c = gcnew String(scheduleBox->SelectedItem->ToString());
MarshalString(c, a);
filestream << a;

And here is the MSDN page with the example:
http://msdn.microsoft.com/en-us/library/1b4az623(v=vs.80).aspx

I know it's a pretty simple solution but this took me HOURS of troubleshooting and visiting several forums to finally find something that worked.

自由如风 2024-07-30 22:26:22

对我来说,其中一些消息出现错误。 我有一个 std::string 。 要将其转换为 String^,我必须执行以下操作 String^ sysString = gcnew String(stdStr.c_str()); 其中 sysString 是 System::String^ ,stdStr 是 std::细绳。 希望这对某人有帮助

您可能必须 #include 才能正常工作

For me, I was getting an error with some of these messages. I have an std::string. To convert it to String^, I had to do the following String^ sysString = gcnew String(stdStr.c_str()); where sysString is a System::String^ and stdStr is an std::string. Hope this helps someone

You may have to #include <string> for this to work

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