2009-11-06 19 views
6

मुझे एक सी # प्रोग्राम मिला है जिसे एक अप्रबंधित फ़ंक्शन में चार बफर पास करने की आवश्यकता है। मुझे दो तरीकों से मिल गया है जो विश्वसनीय रूप से काम करने लगते हैं, लेकिन मुझे यकीन नहीं है कि मुझे कौन सा चयन करना चाहिए।सी # से अप्रबंधित फ़ंक्शन को कॉल करना: क्या मुझे स्ट्रिंगबिल्डर पास करना चाहिए या असुरक्षित कोड का उपयोग करना चाहिए?

यहां अप्रबंधित फ़ंक्शन के हस्ताक्षर हैं।

extern "C" __declspec(dllexport) int getNextResponse(char *buffer); 

पहला विकल्प बफर को स्ट्रिंगबिल्डर के रूप में परिभाषित करना है, जैसा कि निम्नानुसार है।

//at class level... 
[DllImport("mydll.dll")] 
static extern int getNextResponse(StringBuilder buffer); 

//in main method body... 
StringBuilder sb = new StringBuilder(" ", 65536); 
int rc = getNextResponse(sb); 

यह सरल है, और यह काम करता है, और मुझे लगता है कि मैं मूल रूप से समझ में क्यों काम करता है क्योंकि StringBuilder पर्दे के पीछे एक बफर है, तो (मुझे लगता है) इंटरॉप परत सिर्फ एक चार को StringBuilder वास्ते है *।

दूसरा विकल्प असुरक्षित कोड का उपयोग कर रहा है।

//at class level... 
[DllImport("mydll.dll")] 
static extern int getNextResponse(byte* buffer); 

//separate method... 
private static unsafe int runGetNextResponse(byte[] buffer) 
{ 
    fixed (byte* p = buffer) 
    { 
     int rc = getNextResponse(p); 
     return rc; 
    }    
} 

//in main method body... 
byte[] b = new byte[65536]; 
int rc = runGetNextResponse(b); 

दूसरा दृष्टिकोण अधिक कोड है, लेकिन यह भी हो रहा है कि यह क्या हो रहा है इसके बारे में और भी स्पष्ट है।

क्या ये दो दृष्टिकोण मूल रूप से एक ही काम कर रहे हैं? क्या एक दूसरे को चुनने का कोई कारण है?

उत्तर

8

मैं दृढ़ता से स्ट्रिंगबिल्डर संस्करण का उपयोग करना पसंद करूंगा।

दोनों के बीच एक बड़ा अंतर नहीं होने वाला है, और असुरक्षित कोड का उपयोग लगभग साफ नहीं है।

मेरी राय में, कोर लाइब्रेरी क्लास का उपयोग करके समस्या को हल करने का कोई तरीका है, बिना स्पष्ट (और आवश्यक) लाभ के असुरक्षित कोड का उपयोग करना एक समयपूर्व अनुकूलन है।

+0

क्या होता है यदि कचरा कलेक्टर स्ट्रिंगबिल्डर को पुनः प्राप्त करता है तो getNextResponse निष्पादन के दौरान एक निश्चित कथन के बिना पारित किया जाता है? आयातित कार्यों में उपयोग किए गए प्रत्येक सूचक पैरामीटर को ठीक किया जाएगा? या मैं कुछ याद कर रहा हूँ? – Luca

2

जबकि मैं निश्चित रूप से वजन नहीं कर सकता, मैं अपने अनुभव साझा कर सकता हूं। मैंने स्ट्रिंगबिल्डर विधि का विशेष रूप से उपयोग किया है और इसमें कोई समस्या नहीं है। मुझे इसका सरल कोड और असुरक्षित से बचना पसंद है।

3

स्ट्रिंगबिल्डर का उपयोग करते समय वरीयता दी जाती है। उदाहरण के लिए मान लें कि आपका getNextResponse विधि में आप कुछ स्थिर चर करने के लिए सूचक की दुकान और एक अन्य विधि में इसका इस्तेमाल करते हैं:

var sb = new StringBuilder(); 
sb.Append("Hello World"); 
int result = getNextResponse(sb); 
Console.WriteLine(result); 
someOtherMethod(); // kaboom: The GC could have already destroyed the string builder. 

असुरक्षित विधि आप की गारंटी देता है:

char* globalPointer; 

int getNextResponse(char *buffer) { 
    globalPointer = buffer; 
    return 0; 
} 

void someOtherMethod() { 
    printf("%s\n", globalPointer); 
} 

अब कामयाब पक्ष को देखो कि स्मृति स्थान चारों ओर स्थानांतरित नहीं किया जाएगा:

byte[] buffer = Encoding.UTF8.GetBytes("Hello World"); 
fixed (byte* p = buffer) 
{ 
    int result = getNextResponse(p); 
    Console.WriteLine(result); 
    someOtherMethod(); // works fine as the buffer address is pinned down in memory 
} 

इस मामले में असुरक्षित संस्करण बेहतर काम करेगा।

0

यह इस बात पर निर्भर करता है कि वास्तव में बफर में डेटा क्या है। यदि यह चरित्र डेटा स्ट्रिंगबिल्डर दृष्टिकोण का उपयोग करता है। यदि यह बाइनरी डेटा इसके बजाय बाइट सरणी का उपयोग करता है, लेकिन असुरक्षित विधि का उपयोग न करें। जबकि आम तौर पर 'असुरक्षित' का अतिरंजित डर थोड़ा मूर्खतापूर्ण है और वारंटी के दौरान इसका उपयोग करने का कोई कारण नहीं है, इस मामले में यह अनावश्यक है। उपयोग करें:

//at class level... 
[DllImport("mydll.dll")] 
static extern int getNextResponse([In, Out] byte[] buffer); 

//in main method body... 
byte[] buffer = new byte[65536]; 
int rc = getNextResponse(buffer); 
1

यह marshalling की लागत पर निर्भर करता है। यदि आप बहुत सारे मार्शलिंग करते हैं या डेटा को मार्शल किया जाता है तो बड़ा होता है, तो आप स्ट्रिंग बिल्डर बफर को हर बार बनाने/नष्ट करने के बजाय बफर का पुन: उपयोग करना चाह सकते हैं।

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