सुरक्षित क्या है?

मैं वीबी 6 का उपयोग कर एक ActiveX EXE के निर्माण पर काम कर रहा हूं, और मुझे मिला एकमात्र उदाहरण डेल्फी में लिखा गया है।

उदाहरण कोड पढ़ना, मैंने देखा कि कुछ ऐसे फ़ंक्शन हैं जिनके हस्ताक्षर safecall कीवर्ड के बाद होते हैं। यहां एक उदाहरण दिया गया है:

function AddSymbol(ASymbol: OleVariant): WordBool; safecall;

इस खोजशब्द का उद्देश्य क्या है?

0
<< a href = "http://en.wikipedia.org/wiki/X86_calling_conventions#safecall>" rel = "nofollow noreferrer"> en.wikipedia.org/wiki/X86_calling_conventions#safecall> ;
जोड़ा लेखक Greg Hewgill, स्रोत

4 उत्तर

COM में, प्रत्येक विधि एक फ़ंक्शन है जो HRESULT देता है:

IThingy = interface
   ['{357D8D61-0504-446F-BE13-4A3BBE699B05}']
   function AddSymbol(ASymbol: OleVariant; out RetValue: WordBool): HRESULT; stdcall;
end;

यह COM में एक पूर्ण नियम है:

  • COM
  • में कोई अपवाद नहीं है
  • सबकुछ एक HRESULT
  • देता है
  • नकारात्मक HRESULT विफलता इंगित करता है
  • उच्च स्तर की भाषाओं में, विफलताओं को अपवादों के लिए मैप किया जाता है

यह COM डिजाइनरों का इरादा था कि उच्च स्तरीय भाषा स्वचालित रूप से अपवाद में विफल विधियों का अनुवाद करेगी।

तो अपनी खुद की भाषा में, COM आमंत्रण HRESULT के बिना प्रतिनिधित्व किया जाएगा। उदा .:

  • Delphi-like: function AddSymbol(ASymbol: OleVariant): WordBool;
  • C#-like: WordBool AddSymbol(OleVariant ASymbol);

डेल्फी में आप कच्चे फ़ंक्शन हस्ताक्षर का उपयोग करना चुन सकते हैं:

IThingy = interface
   ['{357D8D61-0504-446F-BE13-4A3BBE699B05}']
   function AddSymbol(ASymbol: OleVariant; out RetValue: WordBool): HRESULT; stdcall;
end;

और खुद को अपवादों को बढ़ाने के लिए संभाल लें:

bAdded: WordBool;
thingy: IThingy;
hr: HRESULT;

hr := thingy.AddSymbol('Seven', {out}bAdded);
if Failed(hr) then
    OleError(hr);

या छोटे समकक्ष:

bAdded: WordBool;
thingy: IThingy;
hr: HRESULT;

hr := thingy.AddSymbol('Seven', {out}bAdded);
OleCheck(hr);

या छोटे समकक्ष:

bAdded: WordBool;
thingy: IThingy;

OleCheck(thingy.AddSymbol('Seven'), {out}bAdded);

एचआरएसयूएलटीएस से निपटने के लिए COM का इरादा नहीं था

लेकिन आप डेल्फी से उस नलसाजी को दूर करने के लिए कह सकते हैं, ताकि आप प्रोग्रामिंग के साथ आगे बढ़ सकें:

IThingy = interface
   ['{357D8D61-0504-446F-BE13-4A3BBE699B05}']
   function AddSymbol(ASymbol: OleVariant): WordBool); safecall;
end;

दृश्यों के पीछे, संकलक अभी भी रिटर्न HRESULT की जांच करेगा, और एक EOleSysError अपवाद फेंक देगा यदि HRESULT ने विफलता का संकेत दिया (यानी नकारात्मक था)। कंपाइलर से उत्पन्न safecall संस्करण कार्यात्मक रूप से समतुल्य है:

function AddSymbol(ASymbol: OleVariant): WordBool; safecall;
var
   hr: HRESULT;
begin
   hr := AddSymbol(ASymbol, {out}Result);
   OleCheck(hr);
end;

लेकिन यह आपको बस कॉल करने के लिए स्वतंत्र करता है:

bAdded: WordBool;
thingy: IThingy;

bAdded := thingy.AddSymbol('Seven');

टीएल; डॉ: आप या तो उपयोग कर सकते हैं:

function AddSymbol(ASymbol: OleVariant; out RetValue: WordBool): HRESULT; stdcall;
function AddSymbol(ASymbol: OleVariant): WordBool; safecall;

लेकिन पूर्व में आपको हर बार HRESULT को संभालने की आवश्यकता होती है।

बोनस चेटर

आप लगभग कभी भी HRESULT को संभालना नहीं चाहते हैं; यह शोर के साथ कार्यक्रम को अव्यवस्थित करता है जो कुछ भी नहीं जोड़ता है। लेकिन कभी-कभी आप खुद को HRESULT जांचना चाहेंगे (उदा। आप ऐसी विफलता को संभालना चाहते हैं जो बहुत असाधारण नहीं है)। डेल्फी के कभी भी संस्करणों में अनुवादित विंडोज हेडर इंटरफेस शामिल नहीं हैं जिन्हें दोनों तरीकों से घोषित किया गया है:

IThingy = interface
   ['{357D8D61-0504-446F-BE13-4A3BBE699B05}']
   function AddSymbol(ASymbol: OleVariant; out RetValue: WordBool): HRESULT; stdcall;
end;

IThingySC = interface
   ['{357D8D61-0504-446F-BE13-4A3BBE699B05}']
   function AddSymbol(ASymbol: OleVariant): WordBool); safecall;
end;

या आरटीएल स्रोत से:

  ITransaction = interface(IUnknown)
    ['{0FB15084-AF41-11CE-BD2B-204C4F4F5020}']
    function Commit(fRetaining: BOOL; grfTC: UINT; grfRM: UINT): HResult; stdcall;
    function Abort(pboidReason: PBOID; fRetaining: BOOL; fAsync: BOOL): HResult; stdcall;
    function GetTransactionInfo(out pinfo: XACTTRANSINFO): HResult; stdcall;
  end;

  { Safecall Version }
  ITransactionSC = interface(IUnknown)
    ['{0FB15084-AF41-11CE-BD2B-204C4F4F5020}']
    procedure Commit(fRetaining: BOOL; grfTC: UINT; grfRM: UINT); safecall;
    procedure Abort(pboidReason: PBOID; fRetaining: BOOL; fAsync: BOOL); safecall;
    procedure GetTransactionInfo(out pinfo: XACTTRANSINFO); safecall;
  end;

SC प्रत्यय safecall के लिए खड़ा है। दोनों इंटरफेस समकक्ष हैं, और आप चुन सकते हैं कि आपकी इच्छा के आधार पर आपके COM चर को घोषित करना है:

//thingy: IThingy;
thingy: IThingySC;

आप उनके बीच भी डाल सकते हैं:

thingy: IThingSC;
bAdded: WordBool;

thingy := CreateOleObject('Supercool.Thingy') as TThingySC;

if Failed(IThingy(thingy).AddSymbol('Seven', {out}bAdded) then
begin
   //Couldn't seven? No sixty-nine for you
   thingy.SubtractSymbol('Sixty-nine');
end;

Extra बोनस चेटर - C#

डिफ़ॉल्ट रूप से सी # डेल्फी safecall के समतुल्य है, सी # को छोड़कर:

  • आपको सुरक्षित मैपिंग का चयन करना होगा
  • ऑप्ट-इन
  • के बजाय

सी # में आप अपने COM इंटरफ़ेस को इस प्रकार घोषित करेंगे:

[ComImport]
[Guid("{357D8D61-0504-446F-BE13-4A3BBE699B05}")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IThingy
{
   WordBool AddSymbol(OleVariant ASymbol);
   WordBool SubtractSymbol(OleVariant ASymbol);
}

आप देखेंगे कि COM HRESULT आपके से छिपा हुआ है। डेल्फी कंपाइलर की तरह सी # कंपाइलर स्वचालित रूप से लौटा हुआ HRESULT जांच करेगा और आपके लिए अपवाद फेंक देगा।

और सी # में, डेल्फी में, आप स्वयं HRESULT को संभालने का चयन कर सकते हैं:

[ComImport]
[Guid("{357D8D61-0504-446F-BE13-4A3BBE699B05}")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IThingy
{
   [PreserveSig]
   HRESULT AddSymbol(OleVariant ASymbol, out WordBool RetValue);

   WordBool SubtractSymbol(OleVariant ASymbol);
}

The [PreserveSig] tells the compiler to preserve the method signature exactly as is:

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

0
जोड़ा

सेफकॉल पास्कल की बजाय दाएं से बाएं पैरामीटर पास करता है या बाएं से दाएं रजिस्टर (डिफ़ॉल्ट)

सुरक्षितकॉल के साथ, प्रक्रिया या फ़ंक्शन लौटने पर स्टैक से पैरामीटर हटा देता है (पास्कल की तरह, लेकिन सीडीसीएल की तरह नहीं, जहां यह कॉलर तक है)

सेफकॉल अपवाद 'फ़ायरवॉल' लागू करता है; Win32 पर esp, यह interprocess COM त्रुटि अधिसूचना लागू करता है। यह अन्यथा stdcall के समान होगा (जीत एपीआई के साथ इस्तेमाल अन्य कॉलिंग सम्मेलन)

0
जोड़ा

इसके अतिरिक्त, अपवाद फ़ायरवॉल IEErorInfo का समर्थन करने वाली ऑब्जेक्ट के साथ SetErrorInfo() को कॉल करके काम करते हैं, ताकि कॉलर अपवाद के बारे में विस्तारित जानकारी प्राप्त कर सके। यह Tbject.SafeCallException द्वारा किया जाता है TComObject और TAutoIntfObject दोनों में ओवरराइड। इस तथ्य को चिह्नित करने के लिए इन दोनों प्रकारों में ISupportErrorInfo भी लागू किया गया है।

अपवाद की स्थिति में, सुरक्षितकॉल विधि का कॉलर ISupportErrorInfo के लिए पूछताछ कर सकता है, फिर पूछताछ करें कि इंटरफ़ेस के लिए जिसकी विधि विफलता HRESULT (उच्च बिट सेट) में विफल हुई, और यदि वह S_OK लौटाता है, GetErrorInfo() IErrorInfo कार्यान्वयन के रूप में अपवाद जानकारी (विवरण, सहायता, आदि) प्राप्त कर सकता है SafeCallException ओवरराइड में डेल्फी आरटीएल द्वारा SetErrorInfo() को पास किया गया था) ।

0
जोड़ा

What Francois said and if it wasn't for safecall your COM method call would have looked like below and you would have to do your own error checking instead of getting exceptions.

function AddSymbol(ASymbol: OleVariant; out Result: WordBool): HResult; stdcall;
0
जोड़ा