لماذا يمكن أن دلفي DLLs استخدام WideString دون استخدام ShareMem?

StackOverflow https://stackoverflow.com/questions/9331026

  •  27-10-2019
  •  | 
  •  

سؤال

ديفيد الإجابة على سؤال آخر يظهر دلفي DLL وظيفة العودة WideString.لم اعتقد ابدا ان كان ممكن من دون استخدام 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;

يعمل, وأنا لا أفهم كيف.الاتفاقية أعرف من هو واحد يستخدم من قبل نظام التشغيل Windows API ، على سبيل المثال ويندوز GetClassNameW:

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

معنى المتصل يوفر المخزن المؤقت, و أقصى طول.Windows DLL يكتب إلى المخزن المؤقت مع طول التقادم.المتصل هو تخصص إلغاء تخصيص الذاكرة.

وثمة خيار آخر هو أن DLL تخصيص الذاكرة على سبيل المثال باستخدام LocalAlloc, و المتصل إلغاء تخصيص الذاكرة من خلال الدعوة LocalFree.

كيف يتم تخصيص الذاكرة و deallocation مع DLL سبيل المثال ؟ لا "السحر" يحدث لأن النتيجة هي WideString(BSTR)?و لماذا لم Windows Api أعلن مريحة مع هذه الاتفاقية ؟ (هل هناك أي معروف Win32 واجهات برمجة التطبيقات التي تستخدم هذه الاتفاقية؟)


تحرير:

أنا اختبرت DLL مع C#.
الدعوة SomeFunction1 يسبب AV (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!

هنا متابعة.

هل كانت مفيدة؟

المحلول

A WideString هو نفس BSTR, انها مجرد دلفي اسم.تخصيص الذاكرة يتم التعامل معها من قبل المشترك COM مخصص ، CoTaskMemAlloc.لأن جميع الأطراف استخدام نفس مخصص يمكنك بأمان تخصص في وحدة واحدة و تخصيص آخر.

لذلك السبب لا تحتاج إلى استخدام Sharemem هو أن دلفي كومة الذاكرة المؤقتة غير المستخدمة.بدلا COM كومة الذاكرة المؤقتة غير المستخدمة.و الذي هو مشترك بين جميع وحدات في العملية.

إذا نظرتم إلى دلفي تنفيذ WideString سترى المكالمات التالية واجهات برمجة التطبيقات: SysAllocStringLen, SysFreeString و SysReAllocStringLen.هذه هي منظومة المقدمة BSTR وظائف API.

العديد من واجهات برمجة تطبيقات Windows يمكنك الرجوع إلى ما قبل تاريخ اختراع COM.ما هو أكثر من ذلك ، هناك مزايا الأداء باستخدام ثابت طول المخزن المؤقت المخصص من قبل المتصل.وهي أنه يمكن تخصيصها على المكدس بدلا من كومة.أنا أيضا يمكن أن نتصور أن ويندوز المصممين لا أريد أن قوة كل عملية الربط OleAut32.dll ودفع ثمن الحفاظ على كوم كومة.تذكر أنه عند معظم Windows API تم تصميم وأداء الخصائص النموذجية الأجهزة كانت مختلفة جدا من الآن.

آخر ممكن السبب BSTR أكثر على نطاق واسع هو أن ويندوز API تستهدف C.وإدارة عمر BSTR من C هو أكثر من ذلك بكثير جدا صعبة من أعلى مستوى لغات مثل C++, C#, Delphi.... الخ

هناك إضافية مضاعفات ذلك.دلفي أبي عن WideString عودة القيم غير متوافق مع Microsoft أدوات.يجب عدم استخدام WideString بمثابة عودة نوع بدلا العودة عبر out معلمة.لمزيد من التفاصيل انظر لماذا يمكن WideString لا ترجع الدالة قيمة interop?

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top