2011-01-14 17 views
7

पर सी # GUI लिखना मेरे पास एक सी ++ कंसोल एक्स है जो कुछ प्रोगोगिंग करता है। अब मैं एक सी # जीयूआई लिखना चाहता था जो कुछ प्रोग्रामिंग करता है जो सी ++ exe करता है। मैं कुछ तरीकों में से सोच रहा था,सी ++ डीएल या सी ++ exe

  1. सी में सभी प्रोग्रामिंग ++ खरोंच से किया साथ सी # जीयूआई लिखें।
  2. एक सी का निर्माण (मैं rework की राशि यह जरूरत पर जोर देता के लिए यह करने के लिए नहीं करना चाहते हैं) ++ dll जो प्रोग्रामिंग करता है और इसे जीयूआई ऐप में आयात किया गया है। (अब यहां मुझे चिंता है। मैं सी ++ डीएल में दिनचर्या के आउटपुट को कैप्चर कैसे करूं और इसे जीयूआई में प्रदर्शित करूं? क्या मुझे आउटपुट को प्रत्येक दिनचर्या के लिए स्ट्रिंग के रूप में वापस करना चाहिए कॉल। चूंकि मैं नहीं जानता कि प्रबंधित सी ++ आईएएम एक अप्रबंधित सी ++ डीएल बनाने जा रहा है।)
+0

आप एक COM इंटरफेस जोड़ने विचार किया है? चूंकि, आईएमएचओ, COM कंटेनर के साथ तर्क और प्रोग्राम डेटा पास करने का समाधान हो सकता है। –

उत्तर

7

सी ++/सीएलआई डीएल बनाना वास्तव में कठिन नहीं है। आप मूल रूप से अप्रबंधित सी ++ कोड का उपयोग करते हैं, सिवाय इसके कि आप एक "public ref class" परिभाषित करते हैं जो उन कार्यों को होस्ट करता है जिन्हें आप सी # कोड देखना चाहते हैं।

किस प्रकार का डेटा आप लौट रहे हैं? एकल संख्या, संख्याओं की matrices, जटिल वस्तुओं?

अद्यतन: चूंकि यह स्पष्ट किया गया है कि "आउटपुट" iostreams है, here is a project लाइब्रेरी को कॉल करने वाले .NET अनुप्रयोग में cout की पुनर्निर्देशन का प्रदर्शन करता है। रीडायरेक्ट कर रहा है clog या cerr बस के बाद मौजूदा अनुप्रेषित नमूनों DllMain में अतिरिक्त लाइनें का एक मुट्ठी भर की आवश्यकता होगी।

The zip file VS2010 परियोजना फाइलों शामिल है, लेकिन स्रोत कोड भी 2005 में काम करना चाहिए या 2008

iostreams कब्जा कार्यक्षमता निम्न कोड में निहित है:

// compile this part without /clr 
class capturebuf : public std::stringbuf 
{ 
protected: 
    virtual int sync() 
    { 
     // ensure NUL termination 
     overflow(0); 
     // send to .NET trace listeners 
     loghelper(pbase()); 
     // clear buffer 
     str(std::string()); 
     return __super::sync(); 
    } 
}; 

BOOL WINAPI DllMain(_In_ HANDLE _HDllHandle, _In_ DWORD _Reason, _In_opt_ LPVOID _Reserved) 
{ 
    static std::streambuf* origbuf; 
    static capturebuf* altbuf; 
    switch (_Reason) 
    { 
    case DLL_PROCESS_ATTACH: 
     origbuf = std::cout.rdbuf(); 
     std::cout.rdbuf(altbuf = new capturebuf()); 
     break; 
    case DLL_PROCESS_DETACH: 
     std::cout.rdbuf(origbuf); 
     delete altbuf; 
     break; 
    } 

    return TRUE; 
} 

// compile this helper function with /clr 
void loghelper(char* msg) { Trace::Write(gcnew System::String(msg)); } 
+0

मैं सी # जीयूआई में सी ++ डीएलएल से आने वाले लॉग संदेश प्रदर्शित करना चाहता हूं। – excray

+0

@ user97642: तो सी ++ डीएलएल 'std :: clog' पर लिख रहा है और आप इस आउटपुट को सी # में भेजना चाहते हैं? –

+0

हां क्लोग या कोउट या सीर। – excray

3

तो आप प्रबंधित सीनेट कोड से सी ++ लाइब्रेरी को कॉल करना चाहते हैं?

फिर आपको सी ++ में COM COM या P-invokable लाइब्रेरी बनाने की आवश्यकता होगी। आपके दृष्टिकोण की आवश्यकता के आधार पर प्रत्येक दृष्टिकोण के अपने पेशेवर और विपक्ष हैं। आपको अपने उपभोक्ता में डेटा मार्शल करना होगा। दोनों अवधारणाओं पर बहुत सारी सामग्री हैं।

0

आप केवल एक सी # जीयूआई रैपर लिख सकते हैं (जैसा कि आप विकल्प 2 में सुझाव देते हैं) और सी ++ प्रक्रिया को जन्म देते हैं; हालांकि, यह थोड़ा धीमा होगा (मुझे नहीं पता कि यह मायने रखता है)।

अपने सी ++ exe चलाने के लिए और आउटपुट कैप्चर करने के लिए आप ProcessRunner का उपयोग कर सकते हैं। यहाँ मूल उपयोग है:

using CSharpTest.Net.Processes; 
partial class Program 
{ 
    static int Main(string[] args) 
    { 
     ProcessRunner run = new ProcessRunner("svn.exe", "update"); 
     run.OutputReceived += new ProcessOutputEventHandler(run_OutputReceived); 
     return run.Run(); 
    } 

    static void run_OutputReceived(object sender, ProcessOutputEventArgs args) 
    { 
     Console.WriteLine("{0}: {1}", args.Error ? "Error" : "Output", args.Data); 
    } 
} 
+0

आईएएम दूसरे विकल्प को समझने के लिए एक रास्ता तलाश रहा है। सी ++ डीएलएल का उपयोग कर एक सी # जीयूआई। – excray

0

शायद यहां जाने के लिए सबसे अच्छा तरीका है रीडायरेक्ट करने के लिए उपयोग पी/आह्वान या प्लेटफार्म आह्वान है। संरचना या आपके सी ++ डीएल इंटरफ़ेस के आधार पर आप इसे शुद्ध सी इंटरफ़ेस में लपेटना चाहते हैं; यदि आपका इंटरफ़ेस केवल blittable प्रकारों का उपयोग करता है तो यह सबसे आसान है। यदि आप अपने डीएल इंटरफेस को ब्लिटेबल प्रकारों (इंट 32, सिंगल, बूलियन, इंट 32 [], सिंगल [], डबल [] - मूलभूत) तक सीमित करते हैं तो आपको प्रबंधित (सी #) के बीच डेटा की जटिल जटिलता करने की आवश्यकता नहीं होगी। और अप्रबंधित (सी) स्मृति रिक्त स्थान।

उदाहरण के लिए, आपके सी # कोड में आप DllImport विशेषता का उपयोग करके अपने सी/सी ++ डीएल में उपलब्ध कॉल को परिभाषित करते हैं।

[DllImport, "ExactDllName.dll"] 
static extern boolean OneOfMyCoolCRoutines([In] Double[] x, [In] Double[] y, [Out] Double result) 

थोड़ा [में] की और [बाहर] की सख्ती से आवश्यक नहीं हैं, लेकिन वे साथ इसकी गति कर सकते हैं। अब आपके सी # प्रोजेक्ट के संदर्भ के रूप में अपना "ExactDllName.dll" जोड़ा गया है, तो आप अपने सी # सी से अपने सी/सी ++ फ़ंक्शन को कॉल कर सकते हैं।

fixed(Double *x = &x[0], *y = &y[0]) 
{ 
    Boolean returnValue = OneOfMyCoolCRoutines(x, y, r); 
} 

ध्यान दें कि मैं अनिवार्य रूप से वापस और चौथे मेरी dll और सी # कोड के बीच संकेत गुजर रहा हूँ। इससे स्मृति कीड़े पैदा हो सकती हैं क्योंकि उन सरणी के स्थान सीएलआर कचरा कलेक्टर द्वारा बदला जा सकता है, लेकिन सी/सी ++ डीएल इसके बारे में कुछ भी नहीं जान पाएगा। तो इसके खिलाफ सुरक्षा के लिए, मैंने बस उन बिंदुओं को अपने सी # में ठीक कर दिया है, और अब वे स्मृति में नहीं चले जाएंगे जबकि मेरा डीएल उन सरणी पर काम कर रहा है। यह अब असुरक्षित कोड है और मुझे अपने सी # कोड डब्ल्यू/उस ध्वज को संकलित करने की आवश्यकता होगी।

भाषा इंटरऑप के लिए बहुत बढ़िया विवरण हैं, लेकिन आपको रोलिंग करना चाहिए। यदि संभव हो तो ब्लिटेबल प्रकारों के एक स्टेटलेस सी इंटरफेस पर चिपकना एक महान नीति है। यह आपकी भाषा इंटरऑप कोड को सबसे साफ रखेगा।

गुड लक,

पॉल

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