2009-06-03 22 views

Trả lời

37

Kiểm tra System::Runtime::InteropServices::Marshal::StringToCoTaskMemUni() và bạn bè của nó.

Rất tiếc, không thể đăng mã ngay bây giờ; Tôi không có VS trên máy này để kiểm tra nó biên dịch trước khi gửi bài.

9

Dưới đây là một số quy trình chuyển đổi tôi đã viết nhiều năm trước cho dự án C++/cli, chúng nên vẫn hoạt động.

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; 
    } 
+0

Những gì bạn cần để chạy? Bao gồm các tệp, v.v. ????? – alap

+0

@alap, Sử dụng ** Hệ thống :: Thời gian chạy :: InteropServices :: Marshal ** hoặc write ** bằng cách sử dụng không gian tên System :: Runtime :: InteropServices; **. – neo

118

Không cuộn của riêng bạn, sử dụng these các gói đóng gói tiện dụng (và có thể mở rộng) do Microsoft cung cấp.

Ví dụ:

#include <msclr\marshal_cppstd.h> 

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

thx cho liên kết hữu ích này, gợi ý này đã lưu cho tôi rất nhiều mã hóa. như một lưu ý phụ: các mẫu/lớp nằm trong #include (ví dụ: #include ) và trong msclr :: interop namespace, hãy xem ví dụ tại http://msdn.microsoft.com/de -de/library/vstudio/bb384859 (v = vs.90) .aspx) – Beachwalker

+2

Mặc dù tiện ích này hoàn toàn thiếu hỗ trợ mã hóa thích hợp. Xem thêm câu hỏi SO của tôi: http://stackoverflow.com/questions/18894551/string-marshalling-with-marshal-as-and-encodings. Giả định của tôi là marshal_as chuyển đổi chuỗi Unicode thành ACP trong chuỗi std ::. –

19

này đã làm việc cho tôi:

#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; 
+2

Bản dịch tiếng Anh: "Tôi sẽ trả lời bài đăng này cũng: p. Đây là chức năng của tôi." – sivabudh

+0

Muchas gracias, Alejandro! – sivabudh

5

Tôi đã mất nhiều giờ cố gắng để chuyển đổi một hình thức cửa sổ giá trị listbox ToString thành một chuỗi tiêu chuẩn để tôi có thể sử dụng nó với fstream để xuất ra một tệp txt. My Visual Studio đã không đi kèm với các tập tin tiêu đề marshal mà một số câu trả lời tôi thấy nói để sử dụng. Sau rất nhiều thử và sai cuối cùng tôi đã tìm thấy một giải pháp cho các vấn đề mà chỉ sử dụng hệ thống :: 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; 

Và đây là trang MSDN với ví dụ: http://msdn.microsoft.com/en-us/library/1b4az623(v=vs.80).aspx

tôi biết đó là một giải pháp khá đơn giản nhưng điều này đã cho tôi GIỜ của xử lý sự cố và ghé thăm một số diễn đàn để cuối cùng tìm thấy một cái gì đó mà làm việc.

36

Bạn có thể dễ dàng làm được điều này như sau

#include <msclr/marshal_cppstd.h> 

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

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

+1 cho giải pháp ngắn và đơn giản và ví dụ đơn giản (mặc dù có thêm dấu ngoặc đơn ở cuối mã của bạn) –

+0

Đây là giải pháp duy nhất trả lời trực tiếp câu hỏi. – Jiminion

+2

hmm ... 33 phiếu bầu cho một câu trả lời đã được cung cấp hơn 2 năm trước đó với gần như cùng một dòng mã. tôn trọng để đạt được rất nhiều điểm cho điều đó. ;-) – Beachwalker

4

Tôi tìm thấy một cách dễ dàng để có được một std :: string từ một String^là sử dụng sprintf().

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

Không cần phải gọi hàm Marshal!

CẬP NHẬT Nhờ Eric, tôi đã sửa đổi mã mẫu để kiểm tra kích thước của chuỗi đầu vào để ngăn chặn tràn bộ đệm.

+1

Đó là một quyết định tò mò để giới thiệu một lỗ hổng tràn bộ đệm trong mã của bạn chỉ để tránh các chức năng gọi điện được thiết kế đặc biệt để sắp xếp chuỗi. – Eric

+0

Tôi chỉ trình bày một cách tiếp cận khác nếu ai đó không muốn sử dụng các chức năng của nguyên soái. Tôi đã thêm một kiểm tra kích thước để ngăn chặn tràn. – Ionian316

+0

@Eric Nội bộ nó là marshalling cho bạn. Xem [câu trả lời SO này] (http: // stackoverflow.com/a/11831686/1516125) để biết chi tiết. Nếu bạn kiểm tra kích thước trước, bạn sẽ không gặp phải bất kỳ vấn đề tràn nào và mã sẽ sạch hơn nhiều. – Ionian316

0

Tôi thích tránh xa người marshaller.

Using CString newString(originalString); 

Dường như tôi sạch hơn và nhanh hơn. Không cần phải lo lắng về việc tạo và xóa một ngữ cảnh.

0

// Tôi sử dụng VS2012 để viết dưới đây code-- convert_system_string để 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; 
     } 
1

C# sử dụng định dạng UTF16 cho chuỗi của nó.
Vì vậy, ngoài việc chuyển đổi các loại, bạn cũng nên ý thức về định dạng thực tế của chuỗi.

Khi biên dịch cho Bộ ký tự nhiều byte Visual Studio và API Win giả định UTF8 (Mã hóa cửa sổ thực tế là Windows-28591).
Khi biên dịch cho Bộ ký tự Unicode Visual studio và API Win giả định UTF16.

Vì vậy, bạn cũng phải chuyển đổi chuỗi từ định dạng UTF16 sang UTF8 và không chỉ chuyển thành chuỗi std ::.
Điều này sẽ trở nên cần thiết khi làm việc với các định dạng đa ký tự như một số ngôn ngữ không phải latin.

Ý tưởng là quyết định rằng std::wstringluôn là đại diện cho UTF16.
std::stringluôn là đại diện cho UTF8.

Điều này không được thực thi bởi trình biên dịch, đó là một chính sách tốt để có.

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

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

Hoặc có nó trong một cú pháp nhỏ gọn hơn:

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ác vấn đề liên quan