2010-02-01 15 views
10

कनवर्ट करने की आवश्यकता है मैं वर्तमान दिनांक और समय प्राप्त करने के लिए .NET डेटटाइम का उपयोग कर रहा हूं। मैं फ़ाइल नाम के हिस्से के रूप में उपयोग करने के लिए इसे एक स्ट्रिंग में परिवर्तित कर रहा हूं। समस्या यह है कि किसी छवि को सहेजने के लिए OpenCV कमांड को एक char * स्ट्रिंग प्रकार की आवश्यकता नहीं होती है, और डेटटाइम केवल स्ट्रिंग^प्रकार आउटपुट करेगा। मैं यह काम कैसे पूरा कर सकता हूं? यहाँ कोडस्ट्रिंग^से char *

String^ nowString = DateTime::Now.ToString("yyyy-MM-dd-HH:mm"); 
     IplImage* toSave; 
     CvCapture* capture = cvCreateCameraCapture(0); 
     toSave = cvQueryFrame(capture); 
     cvSaveImage(nowString, toSave); 
     cvReleaseImage(&toSave); 
     cvReleaseCapture(&capture); 
+5

क्यों सभी सीएपीएस? क्या आप चिंतित हैं? –

+1

संभवतः उसके कैप्स लॉक फंस गया है। यह भी समझाया गया है कि उन्होंने टोपी के बिना ".net" क्यों लिखा। – jalf

+0

गलती से कैप्स लॉक – kman99

उत्तर

0

पूरा नहीं आप के बारे में सी ++ इंटरॉप और डेटा मार्शलिंग पढ़ने की जरूरत है।

असल में: यदि आप एक सी ++ TCHAR सरणी के लिए नेट String "डाली" की जरूरत है।

इस देखें: http://msdn.microsoft.com/en-us/library/ef4c3t39(VS.80).aspx

0

रैंडम Googling मुझे यह मिल गया। शायद कोई इसे छोटा कर सकता है?

cli::array<char>^ bytes = Encoding::ASCII::GetBytes(nowString); 
pin_ptr<char> pinned = &bytes[0]; 
std::string nativeString((char*)pinned, bytes->Length); 
char const* chars = nativeString.c_str(); 

संपादित करें: यह मार्शल वर्ग के संचालन से अधिक लंबा है, लेकिन अधिक एन्कोडिंग के साथ काम करता है। आपके मामले में, ऐसा लगता है कि सरल StringToHGlobalAnsi दृष्टिकोण आपको जो भी चाहिए, वह करेगा।

Marshal class में
0

उपयोग StringToXxxAnsi कार्यों एक char* बफर आवंटित करने के लिए है, तो एक ही कक्षा से उचित कार्यों के लिए उन्हें मुक्त करने के लिए।

15

आपकी सर्वश्रेष्ठ शर्त StringToHGlobalAnsi का उपयोग करना है। यहां पूरा कोड दिखाया गया है कि यह कैसे आवंटित स्मृति को मुक्त करने और याद रखने के लिए याद किया गया है।

using namespace System::Runtime::InteropServices; 

void MethodName() 
{ 
    String^ nowString = DateTime::Now.ToString("yyyy-MM-dd-HH:mm"); 
    IntPtr ptrToNativeString = Marshal::StringToHGlobalAnsi(nowString); 
    try 
    { 
     CvCapture* capture = cvCreateCameraCapture(0); 
     IplImage* toSave = cvQueryFrame(capture); 
     cvSaveImage(static_cast<char*>(ptrToNativeString.ToPointer()), toSave); 
     cvReleaseImage(&toSave); 
     cvReleaseCapture(&capture); 
    } 
    catch (...) 
    { 
     Marshal::FreeHGlobal(ptrToNativeString); 
     throw; 
    } 
    Marshal::FreeHGlobal(ptrToNativeString); 
} 

आप एक का उपयोग कर पर पुनर्विचार करना चाह सकते हैं ':' फ़ाइल नाम में चरित्र, जैसा कि मैंने खिड़कियों पर विश्वास नहीं है बहुत ज्यादा यह पसंद है।

+0

यह होगा मार्शल :: FreeCoTaskMem() के बजाय मार्शल :: FreeHGlobal() का उपयोग करने के लिए अधिक उपयुक्त है? StringToHGlobalAnsi() के लिए मेरी एमएसडीएन मदद स्मृति को मुक्त करने के लिए FreeHGlobal() का उपयोग करती है। – cmw

+0

हां, उचित कॉल; संपादित करें। मुझे लगता है कि मैं डिफ़ॉल्ट रूप से FreeCoTaskMem का उपयोग करने की आदत में आया हूं। – mcdave

+0

पॉइंटर को दो बार मुक्त करने के लिए कोड लिखने के बजाय आप अंततः उपयोग कर सकते हैं। कोशिश करें {...} अंत में {मार्शल :: फ्रीएचजीएलबल (...)} ' –

4

वास्तव में, मैं एक String^ से एक char * प्राप्त करने के लिए सबसे आसान रास्ता मिल गया अच्छा ol 'sprintf() उपयोग करने के लिए है। आपके मामले में तो, आप सरल कर सकते हैं:

char cNow[17] = { 0 }; 
String^ nowString = DateTime::Now.ToString("yyyy-MM-dd-HH:mm"); 
if (nowString->Length < sizeof(cNow)) // make sure it fits & allow space for null terminator 
    sprintf(cNow, "%s", nowString); 

Marshal कार्यों कॉल करने के लिए कोई ज़रूरत नहीं!

अद्यतन

तो ऐसा लगता है कि वी.एस. 2015, सी ++ 11 मानकों के और अधिक बारीकी से पालन करता है तो नेट स्ट्रिंग के साथ sprintf() का उपयोग कर काम नहीं करेगा। फिर इस काम करना चाहिए

#include <msclr/marshal_cppstd.h> 
using namespace msclr::interop; 

:

char cNow[17] = { 0 }; 
String^ nowString = DateTime::Now.ToString("yyyy-MM-dd-HH:mm"); 
string sNow = marshal_as<string>(nowString); 
if (sNow.length() < sizeof(cNow)) // make sure it fits & allow space for null terminator 
    sprintf(cNow, "%s", sNow.c_str()); 

अन्यथा, अगर आप नहीं चाहते

अपने कोड से पहले इन पंक्तियों को शामिल करें: सबसे आसान तरीका है marshal_as() समारोह इस तरह उपयोग करने के लिए है marshal_as() फ़ंक्शन का उपयोग करने के लिए, आप इस तरह के चरित्र द्वारा स्ट्रिंग वर्ण की प्रतिलिपि बना सकते हैं:

char cNow[17] = { 0 }; 
String^ nowString = DateTime::Now.ToString("yyyy-MM-dd-HH:mm"); 
if (nowString->Length < sizeof(cNow)) // make sure it fits & allow space for null terminator 
{ 
    for (int i = 0; i < nowString->Length; i++) 
     cNow[i] = static_cast<char>(nowString[i]); 
} 
+0

वैसे मैं संदेहजनक था - कुछ भी इतना आसान नहीं है - लेकिन ऐसा लगता है (विजुअल स्टूडियो 2012 के साथ)। क्या दृश्यों के पीछे कुछ भी बुरा हो रहा है जिसका मतलब है कि हमें यह नहीं करना चाहिए? – njplumridge

+0

@ एनजेप्लुमिज मैं इस तकनीक के बारे में सीखा जब भी मैं उलझन में था। मुझे लगता है कि यह दृश्यों के पीछे marshalling कर रहा है, लेकिन दूसरों को इसके बारे में और अधिक पता हो सकता है। हालांकि यह सभी जटिलता छुपाता है। मैं sprintf() बफर ओवरफ्लो को रोकने से पहले आकार के लिए एक चेक करूँगा। ऊपर मेरा संपादन देखें। – Ionian316

+0

@njplumridge यह दृश्यों के पीछे marshalling कर रहा है। विवरण के लिए [यह SO उत्तर] देखें (http://stackoverflow.com/a/11831686/1516125)। – Ionian316

संबंधित मुद्दे