2012-02-17 10 views
19

David's answer to another question एक WideString लौटने एक डेल्फी DLL समारोह को दर्शाता है। मैंने कभी सोचा नहीं कि ShareMem के उपयोग के बिना संभव था।डेल्फी डीएलएल ShareMem का उपयोग किए बिना वाइडस्ट्रिंग का उपयोग क्यों कर सकता है?

मेरा परीक्षण DLL:

function SomeFunction1: Widestring; stdcall; 
begin 
    Result := 'Hello'; 
end; 

function SomeFunction2(var OutVar: Widestring): BOOL; stdcall; 
begin 
    OutVar := 'Hello'; 
    Result := True; 
end; 

मेरे फोन करने वाले कार्यक्रम:

function SomeFunction1: WideString; stdcall; external 'Test.dll'; 
function SomeFunction2(var OutVar: Widestring): BOOL; stdcall; external 'Test.dll'; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    W: WideString; 
begin 
    ShowMessage(SomeFunction1); 
    SomeFunction2(W); 
    ShowMessage(W); 
end; 

यह काम करता है, और मैं कैसे समझ में नहीं आता।

function GetClassNameW(hWnd: HWND; lpClassName: PWideChar; nMaxCount: Integer): Integer; stdcall; 

फोन करने वाले अर्थ बफर प्रदान करता है, और अधिकतम लंबाई: सम्मेलन मैं के बारे में पता Windows API द्वारा प्रयोग किया जाता है, उदाहरण के लिए Windows GetClassNameW के लिए है। विंडोज डीएलएल लंबाई सीमा के साथ उस बफर को लिखता है। कॉलर स्मृति आवंटित और हटा देता है।

एक अन्य विकल्प है कि DLL LocalAlloc का उपयोग करके उदाहरण के लिए स्मृति को आबंटित है, और कोलर LocalFree फोन करके स्मृति deallocates।

कैसे स्मृति आवंटन और मेरे DLL उदाहरण के साथ आवंटन रद्द करने काम करता है? क्या "जादू" होता है क्योंकि परिणाम WideString (BSTR) है? और इस तरह के सुविधाजनक सम्मेलन के साथ विंडोज एपीआई क्यों घोषित नहीं किए गए हैं? (वहाँ किसी भी ज्ञात Win32 API, सम्मेलन का उपयोग करता है क्या?)


संपादित करें:

मैं के साथ सी # DLL परीक्षण किया गया।
कॉलिंग SomeFunction1 एक एवी (Attempted to read or write protected memory) का कारण बनता है।
SomeFunction2 ठीक काम करता है।

[DllImport(@"Test.dll")] 
[return: MarshalAs(UnmanagedType.BStr)] 
static extern string SomeFunction1(); 

[DllImport(@"Test.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool SomeFunction2([MarshalAs(UnmanagedType.BStr)] out string res); 

... 

string s; 
SomeFunction2(out s); 
MessageBox.Show(s); // works ok 
MessageBox.Show(SomeFunction1()); // fails with AV! 

यहाँ एक followup है।

उत्तर

23

WideStringBSTR जैसा ही है, यह केवल इसके लिए डेल्फी नाम है। स्मृति आवंटन को साझा COM आवंटक, CoTaskMemAlloc द्वारा प्रबंधित किया जाता है। चूंकि सभी पार्टियां एक ही आवंटक का उपयोग करती हैं, इसलिए आप सुरक्षित रूप से एक मॉड्यूल में आवंटित कर सकते हैं और दूसरे में स्थानांतरित कर सकते हैं।

तो, कारण आप Sharemem उपयोग करने के लिए की जरूरत नहीं है कि डेल्फी ढेर इस्तेमाल नहीं किया जा रहा है। इसके बजाय COM ढेर का उपयोग किया जाता है। और यह एक प्रक्रिया में सभी मॉड्यूल के बीच साझा किया जाता है।

यदि आप वाइडस्ट्रिंग के डेल्फी कार्यान्वयन को देखते हैं तो आपको निम्न API पर कॉल दिखाई देगी: SysAllocStringLen, SysFreeString और SysReAllocStringLen। ये सिस्टम BSTR API functions प्रदान किए गए हैं।

विंडोज एपीआई से कई आप की तारीख पूर्व कॉम के आविष्कार का संदर्भ लें। और भी, कॉलर द्वारा आवंटित एक निश्चित लंबाई बफर का उपयोग करने के लिए प्रदर्शन लाभ हैं। अर्थात् यह ढेर के बजाय ढेर पर आवंटित किया जा सकता है। मैं भी कल्पना कर सकते हैं कि विंडोज डिजाइनरों OleAut32.dll से लिंक और COM ढेर को बनाए रखने की कीमत अदा करने के लिए हर प्रक्रिया के लिए मजबूर नहीं करना चाहती। याद रखें कि जब अधिकांश विंडोज एपीआई डिज़ाइन किया गया था, तो सामान्य हार्डवेयर की प्रदर्शन विशेषताएं अब से बहुत अलग थीं।

BSTR का उपयोग कर अधिक व्यापक रूप से नहीं करने के लिए एक अन्य संभावित कारण है कि Windows API सी पर लक्षित है और BSTR सी से के जीवनकाल के प्रबंध बहुत सी ++, सी #, डेल्फी आदि

की तरह उच्च स्तर भाषाओं से की तुलना में अधिक मुश्किल है
+0

उत्तर देने के लिए धन्यवाद। देखो [यहां] (http://stackoverflow.com/a/5007216/937125)। मेरी समझ यह है कि डीएलएल को 'CoTaskMemAlloc' कॉल करना चाहिए। डेल्फी इसे आवंटित करते समय कॉल करता है 'वाइडस्ट्रिंग'? भी, 'CoTaskMemFree' कब कहा जाता है? – kobik

+1

'SysXXX' फ़ंक्शन COM आवंटक को आवश्यक कॉल करते हैं। –

+0

आपकी टिप्पणी में लिंक केवल इस तथ्य को बताता है कि पी/आक्रमण मार्शलर मानता है कि 'स्ट्रिंग' प्रकार का रिटर्न वैल्यू 'CoTaskMemAlloc' के साथ आवंटित किया गया था और इसलिए इसे' कोटास्कमेम फ्री 'कहा जाता है जब उसने मार्शलिंग समाप्त कर दी है। –

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