2010-02-01 14 views
12

पर मैंने अलग-अलग चीजों की कोशिश की लेकिन मैं इंटरऑप के साथ पागल हो रहा हूं।सी #+ को सी # स्ट्रिंग पास करें और सी ++ परिणाम (स्ट्रिंग, चार * .. जो भी हो) सी #

(यहां शब्द स्ट्रिंग को एक चरबी प्रकार के रूप में संदर्भित नहीं किया गया है लेकिन "char का संग्रह"): मेरे पास एक डीएनएल में परिभाषित एक अप्रबंधित सी ++ फ़ंक्शन है, जिसे मैं सी # से एक्सेस करने का प्रयास कर रहा हूं, यह फ़ंक्शन एक स्ट्रिंग पैरामीटर और स्ट्रिंग रिटर्न वैल्यू है:

string myFunction(string inputString) 
{ 
} 

सी ++ पक्ष में स्ट्रिंग क्या होनी चाहिए? और सी # एक? और इसके लिए किस पैरामीटर को DllImport की आवश्यकता है?

उत्तर

17

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

सी ++ पक्ष को बफर और बफर आकार को पारित करने का एक आम तरीका है। यदि यह GetString में जो कुछ डालना है, उसके लिए पर्याप्त नहीं है, तो बफर आकार परिवर्तक को यह इंगित करने के लिए संशोधित किया गया है कि उचित आकार क्या होगा। कॉलिंग प्रोग्राम (सी #) तब बफर के आकार को उचित आकार में बढ़ा देगा।

इस अपने निर्यात dll समारोह (C++) है:

extern "C" __declspec void GetString(char* buffer, int* bufferSize); 

मिलान सी # होगा निम्नलिखित:

void GetString(StringBuilder buffer, ref int bufferSize); 

तो सी # में इस का उपयोग करने के लिए आप उसके बाद निम्न की तरह कुछ करना होगा :

int bufferSize = 512; 
StringBuilder buffer = new StringBuilder(bufferSize); 
GetString(buffer, ref bufferSize); 
+1

यह सही दृष्टिकोण है। ध्यान दें कि आपको संदर्भ द्वारा बफर आकार को पास करने की आवश्यकता नहीं है। सी/सी ++ स्ट्रिंग को समाप्त करना चाहिए, बफर। टॉस्ट्रिंग() वापसी मूल्य उत्पन्न करता है। –

+0

उत्तर के लिए सभी को धन्यवाद। मैंने कहीं पढ़ा है कि स्ट्रिंगबिल्डर को आउटपुट स्ट्रिंग के लिए उपयोग किया जाता है, लेकिन मुझे इनपुट स्ट्रिंग को C++ फ़ंक्शन करने के लिए भी आवश्यकता है .. मुझे किस प्रकार का उपयोग करना चाहिए? सी ++ पक्ष में मैंने चार * और सी # साइड स्ट्रिंग डाली है, लेकिन यह काम नहीं करती है। अंत में, क्या मैं आउटपुट "स्ट्रिंग" (सी ++ पक्ष) को कॉन्स्ट चार * के रूप में परिभाषित कर सकता हूं? या मेरे पास एक char * होना चाहिए? – Smjert

+0

@Smjert: एक कॉन्स char * का उपयोग करना एक अच्छा तरीका है यदि आप इसे बदल नहीं रहे हैं। यह सी # पक्ष पर एक स्ट्रिंग के लिए बस ठीक करना चाहिए। आप किस प्रकार की समस्याएं देख रहे हैं? –

2

केवल अच्छा तरीका है कि मैं ऐसा करने का पता Managed C++ Extensions का उपयोग कर एक .NET सी ++ आवरण वर्ग लिखने के लिए है, और नेट सी के अन्दर अपनी मूल सी ++ कोड फोन आपत्ति ++। सिस्टम को कनवर्ट करने के लिए प्रबंधित एक्सटेंशन में फ़ंक्शन हैं। एक char * या किसी अन्य प्रकार की अप्रबंधित स्ट्रिंग पर स्ट्रिंग।

मूल रूप से आप सी ++ का उपयोग करके एक .NET कक्षा बनाते हैं और इसे असेंबली से बेनकाब करते हैं, और आंतरिक रूप से उस असेंबली में आप अपने मूल C++ कोड को कॉल कर सकते हैं। दूसरा तरीका पी/इनवॉक का उपयोग करके अपने सी ++ कोड में शुद्ध सी फ़ंक्शन जोड़ना है और फिर अपने सी कोड को सी # से कॉल करें और अपने सी फ़ंक्शन को अपना सी ++ कोड कॉल करें। यह काम करेगा, लेकिन मैं जितना संभव हो सके प्रबंधित कोड का उपयोग करने की कोशिश करता हूं।

2

सी ++ से वापस सी # तक तारों को पार करने की सबसे बड़ी समस्या स्मृति आवंटन है। जीसी को यह जानने में सक्षम होना चाहिए कि इस स्ट्रिंग के लिए आवंटित स्मृति को कैसे साफ किया जाए। चूंकि सी # में व्यापक सीओएम इंटरऑप समर्थन है, इसलिए यह COM BSTRs के बारे में जानता है और इन्हें आवंटित और अस्वीकार कैसे किया जाता है। इस प्रकार ऐसा करने का सबसे आसान तरीका C++ पक्ष पर BSTR और C# पक्ष पर string का उपयोग करना होगा।

नोट, बीएसटी का उपयोग करने से यह संकेत नहीं मिलता है कि आपके फ़ंक्शन को COM के माध्यम से बेनकाब करना होगा।

2

"स्ट्रिंग" वापसी मान समस्या है। पी/Invoc marshaller आपके द्वारा लौटाए गए सूचक पर CoTaskMemFree() को कॉल करने जा रहा है। यह तब तक अच्छा काम नहीं करेगा जब तक आप स्ट्रिंग बफर आवंटित करने के लिए अपने सी/सी ++ कोड में CoTaskMemAlloc() का उपयोग नहीं करते। जो करना काफी असामान्य बात है।

सबसे अच्छा समाधान यह है कि आपके कोड के कॉलर को बफर में पॉइंटर और बफर की लंबाई को तर्क के रूप में पास करने की अनुमति दी जाए। इस तरह सभी स्मृति आवंटन एक तरफ होता है। स्कॉट ने आपको दिखाया कि यह कैसे करें।

1

मैं ++ क्रम में एक multibyte प्रतिनिधित्व करने के लिए एक यूनिकोड सी # स्ट्रिंग परिवर्तित करने के लिए ग में चार को * कन्वर्ट करने के लिए (इस आंशिक एक तरह से हल है)

मैंने पाया निम्नलिखित था बहुत उपयोगी

string st; 
IntPtr stPtr = Marshal.StringToHGlobalAnsi(st); 
// Do your thing in C++ 

Marshal.FreeHGlobal(stPtr); 

यह अक्षम हो सकता है और सी # तरीके से नहीं, मैं सी # के लिए नया हूं, उम्मीद है कि इससे

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