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 है।
उत्तर देने के लिए धन्यवाद। देखो [यहां] (http://stackoverflow.com/a/5007216/937125)। मेरी समझ यह है कि डीएलएल को 'CoTaskMemAlloc' कॉल करना चाहिए। डेल्फी इसे आवंटित करते समय कॉल करता है 'वाइडस्ट्रिंग'? भी, 'CoTaskMemFree' कब कहा जाता है? – kobik
'SysXXX' फ़ंक्शन COM आवंटक को आवश्यक कॉल करते हैं। –
आपकी टिप्पणी में लिंक केवल इस तथ्य को बताता है कि पी/आक्रमण मार्शलर मानता है कि 'स्ट्रिंग' प्रकार का रिटर्न वैल्यू 'CoTaskMemAlloc' के साथ आवंटित किया गया था और इसलिए इसे' कोटास्कमेम फ्री 'कहा जाता है जब उसने मार्शलिंग समाप्त कर दी है। –