C ++ / CLI सिस्टम से परिवर्तित :: स्ट्रिंग ^ से std :: string


90

क्या कोई कृपया एक साधारण कोड पोस्ट कर सकता है जो परिवर्तित होगा,

System::String^

सेवा,

सी ++ std::string

Ie, मैं सिर्फ का मान निर्दिष्ट करना चाहते हैं,

String^ originalString;

सेवा,

std::string newString;

जवाबों:


38

बाहर System::Runtime::InteropServices::Marshal::StringToCoTaskMemUni()और उसके दोस्तों की जाँच करें।

क्षमा करें अब कोड पोस्ट नहीं किया जा सकता; मेरे पास इस मशीन पर वीएस नहीं है यह जांचने के लिए कि यह पोस्ट करने से पहले संकलित है।


159

Microsoft द्वारा प्रदान किए गए इन आसान (और एक्स्टेंसिबल) रैपर का उपयोग न करें ।

उदाहरण के लिए:

#include <msclr\marshal_cppstd.h>

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

2
इस उपयोगी लिंक के लिए thx, इस संकेत ने मुझे बहुत सारे कोडिंग से बचाया। साइड नोट के रूप में: टेम्प्लेट / क्लासेस #include <msclr \ *। h> (जैसे #include <msclr \ marshal.h>) और msclr :: इंटरॉप नेमस्पेस में हैं, msdn.microsoft.com पर एक उदाहरण देखें। /de-de/library/vstudio/bb384859(v=vs.90).aspx )
Beachwalker

4
हालांकि यह सुविधाजनक है, यह पूरी तरह से उचित एन्कोडिंग समर्थन का अभाव है। मेरा SO प्रश्न भी देखें: stackoverflow.com/questions/18894551/… । मेरी धारणा यह है कि marshal_as यूनिकोड स्ट्रिंग्स को एसीपी में std :: string में रूपांतरित करता है।
माइक लिस्चके

MS अनुशंसा है कि रूपांतरण के बाद marshal_context का उपयोग करें और इसे हटा दें। लिंक: msdn.microsoft.com/en-us/library/bb384856.aspx
Ruslan Makrenko

40

आप इस प्रकार से आसानी से कर सकते हैं

#include <msclr/marshal_cppstd.h>

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

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

एक छोटे और सरल समाधान और सरल काम करने के उदाहरण के लिए +1 (हालांकि आपके कोड के अंत में एक अतिरिक्त कोष्ठक है)
साइमन फोर्सबर्ग

यह एकमात्र समाधान है जो सीधे सवाल का जवाब देता है।
जुमिन

8
हम्म ... एक उत्तर के लिए 33 अपवोट्स जो कोड की लगभग समान पंक्तियों के साथ 2 साल पहले ही दिए गए थे। उसके लिए इतने सारे अंक हासिल करने के लिए सम्मान। ;-)
समुद्र तट

20

यह मेरे लिए काम किया:

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

3
अंग्रेजी अनुवाद: "मैं इस पोस्ट का भी जवाब देने जा रहा हूं: p। यह मेरा कार्य है।"
शिवाबुध

9

यहाँ कुछ रूपांतरण रूटीन हैं जो मैंने कई साल पहले 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;
    }

@alap, सिस्टम का उपयोग करें :: रनटाइम :: InteropServices :: मार्शल या नेमस्पेस सिस्टम का उपयोग करके लिखें :: रनटाइम :: InteropServices;
नव

6

मैंने घंटों एक विंडोज़ फॉर्म लिस्टबॉक्स ToString मान को एक मानक स्ट्रिंग में बदलने की कोशिश कर रहा है ताकि मैं इसे एक पाठ फ़ाइल में आउटपुट के लिए फ़्लो के साथ उपयोग कर सकूं। मेरा विज़ुअल स्टूडियो मार्शल हेडर फ़ाइलों के साथ नहीं आया था, जिनके उपयोग के लिए मुझे कई उत्तर मिले थे। बहुत परीक्षण और त्रुटि के बाद मुझे अंततः समस्या का हल मिल गया है जो सिर्फ सिस्टम का उपयोग करता है :: रनटाइम :: इंटरोप सर्वर:

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

मुझे पता है कि यह एक बहुत ही सरल उपाय है, लेकिन यह मुझे समस्या निवारण के लिए और कई मंचों पर जाकर आखिरकार कुछ काम करने के लिए मिला।


6

मुझे std पाने के लिए एक आसान तरीका मिला :: स्ट्रिंग a String ^ स्प्रिंटफ () का उपयोग करना है।

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

मार्शल कार्यों को कॉल करने की आवश्यकता नहीं है!

अद्यतन एरिक के लिए धन्यवाद, मैंने बफर ओवरफ्लो को रोकने के लिए इनपुट स्ट्रिंग के आकार की जांच करने के लिए नमूना कोड को संशोधित किया है।


1
यह आपके कोड में बफर अतिप्रवाह भेद्यता को लागू करने के लिए एक जिज्ञासु निर्णय है, विशेष रूप से मार्शेल स्ट्रिंग्स के लिए डिज़ाइन किए गए फ़ंक्शंस से बचने के लिए।
एरिक

अगर कोई मार्शल कार्यों का उपयोग नहीं करना चाहता है, तो मैं बस एक अलग दृष्टिकोण प्रस्तुत कर रहा हूं। मैंने अतिप्रवाह को रोकने के लिए आकार के लिए एक चेक जोड़ा है।
Ionian316

@ एरिक आंतरिक रूप से यह आपके लिए मार्शलिंग है। देखें इस अतः जवाब जानकारी के लिए। यदि आप पहले से आकार की जांच करते हैं, तो आपके पास कोई अतिप्रवाह समस्या नहीं होगी और कोड बहुत अधिक क्लीनर है।
इयान 316

4

C # अपने तार के लिए UTF16 प्रारूप का उपयोग करता है।
इसलिए, केवल प्रकारों को परिवर्तित करने के अलावा, आपको स्ट्रिंग के वास्तविक प्रारूप के बारे में भी सचेत रहना चाहिए।

मल्टी-बाइट कैरेक्टर के लिए संकलन करते समय विजुअल स्टूडियो सेट करता है और विन एपीआई यूटीएफ 8 (वास्तव में विंडोज़ एन्कोडिंग जो कि विंडोज़-28591 है ) मानता है
जब यूनिकोड चरित्र सेट के लिए संकलन दृश्य स्टूडियो और विन एपीआई UTF16 मान।

इसलिए, आपको स्ट्रिंग को UTF16 से UTF8 फॉर्मेट में बदलना होगा, न कि केवल std :: string में कनवर्ट करना होगा।
कुछ गैर-लैटिन भाषाओं जैसे बहु-चरित्र प्रारूपों के साथ काम करते समय यह आवश्यक हो जाएगा।

विचार यह तय करना है कि std::wstring हमेशा UTF16 का प्रतिनिधित्व करता है ।
और std::string हमेशा 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;
}

1
मैं केवल अपने उपयोग के मामले में UTF8 में कनवर्ट करने के महत्व पर जोर देना चाहता हूं: मुझे Win32 OpenFileDialog (जहां मल्टीबाइट वर्णों के साथ फ़ाइल नाम संभव हैं, उदाहरण के लिए एशियाई अक्षरों वाले फ़ाइल नाम) एक std के माध्यम से इंजन कोड को प्राप्त करने के लिए एक फ़ाइल पथ पास करने की आवश्यकता है :: स्ट्रिंग, इसलिए UTF8 में रूपांतरण महत्वपूर्ण था। उत्कृष्ट उत्तर के लिए धन्यवाद!
बजे जेसन मैकक्लेंसी

0

मुझे मार्शेलर से दूर रहना पसंद है।

Using CString newString(originalString);

मुझे बहुत क्लीनर और तेज़ लगता है। एक संदर्भ बनाने और हटाने के बारे में चिंता करने की आवश्यकता नहीं है।


0

// मैंने VS2012 का उपयोग कोड लिखने के लिए किया है- 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;
        }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.