문제

나의 창조 작업 ActiveX EXE 를 사용하여 VB6,그만의 예 나는 모든이며 델파이로 작성.

독서 예제 코드가 있는 어떤 기능을 누구의 서명은 다음 safecall 키워드입니다.예를 들어 다음과 같습니다.

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

의 목적은 무엇인가 이 키워드는?

도움이 되었습니까?

해결책

Safecall 패스를 매개 변수는 오른쪽에서 왼쪽으로는 대신,파스칼 또는 등록부(기본값)왼쪽에서 오른쪽으로

와 safecall,절차 또는 기능을 제거에서 매개 변수는 stack 으로 돌아에(같은 파스칼은,하지만 다음과 같 cdecl 그것은 어디까지 발신자)

Safecall 를 구현하는 예외'방화벽';esp on Win32,이를 구현하는 프로세스 간 COM 오류를 알림.그것은 그렇지 않으면과 동일한 stdcall(다른 호출하는 데 사용되는 규칙으로 승리 api)

다른 팁

또한,방화벽 예외를 호출하여 작업 SetErrorInfo()함께하는 객체 지원 IErrorInfo,그래서는 발신자를 얻을 수 있는 확장된 정보에 대한 예외는 아니다.에 의해 이루어집 TObject.SafeCallException 재정 모두에서 TComObject 및 TAutoIntfObject.이러한 두 종류도를 구현하 ISupportErrorInfo 마이 사실이다.

의 경우에는 예외 safecall 메소드의 호출자를 쿼리할 수 있습 ISupportErrorInfo,다음는 쿼리를 위한 인터페이스에 그의 방법에서 결과 실패 는(높은 비트 세트),그리고 경우에는 반환합니다., GetErrorInfo() 를 얻을 수 있는 예외의 정보(대한 설명,도움,etc., 의 형태로 IErrorInfo 구현에 전달 SetErrorInfo() 에 의해 델파이 RTL 에 SafeCallException 재정의).

무엇을 말했다 Francois 고 그렇지 않았다면 safecall COM 메소드 호출은 것 같은 아래와 당신은 당신의 자신의 오류를 검사를 대신 받고 예외가 있습니다.

function AddSymbol(ASymbol: OleVariant; out Result: WordBool): HResult; stdcall;

COM 에서 모든 메소드가 반환하는 함수는 HRESULT:

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

이것은 절대적으로 규칙에서 COM:

  • 예외가 없 COM
  • 모든 것을 반환하 는
  • 부정적이외의 실패를 나타내
  • 높은 수준에서 언어 장애에 매핑된 예외

그것은 기도의 COM 디자이너는 더 높은 수준 언어로 번역 실패 방법으로는 예외는 아니다.

그래서 자신의 언어,COM 호출로 표시되지 않외.E.g.:

  • 델파이 같은: function AddSymbol(ASymbol: OleVariant): WordBool;
  • C#같은: 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 의도하지 않았를 처리하기 위해 Hresult

요청할 수 있습니다 하지만 델파이를 숨기는 배관에서 당신은,그래서 당신은에서 얻을 수 있습 프로그래밍:

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

뒤에서는 컴파일러는 여전히 확인 는,및 던져 EOleSysError 예외는 경우에 는 표시량(i.e부정적이었).컴파일러에서 생성 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');

tl;박사:중 하나를 사용할 수 있습니다:

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

하지만 이전에 당신을 필요로 처리 Hresult 니다.

보너스 Chatter

당신은 거의 절대로 처리하려면 Hresult 자신;그것은 클러 프로그램으로는 아무것도 추가.그러나 때로는 너를 확인하려 는 자신(예:을 처리할에 실패하지 않는 아주 특별하).결코 버전의 델파이 시작되는 번역 Windows 헤더 인터페이스 선언을 모두 방법:

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;

나에서 RTL 소스:

  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;

추가 보너스 Chatter-C#

C#기본적으로는 해당 Delphi safecall, 를 제외하고,C#:

  • 당신은 탈퇴의 safecall mapping
  • 오히려 이상 선택에서

C#당신이 선언하 COM 인터페이스:

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

는 것을 알 수 있 COM HRESULT 가 숨겨져 있습니다.C#컴파일러,다음과 같은 델파이 컴파일러,자동으로 확인 반 는 던지는 예외에 대한 당신.

과에서는 C#에서와 같이,델파이,당신이 선택할 수 있습을 처리하 Hresult yourself:

[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);
}

[PreserveSig] 컴파일러를 보존하는 방법을 서명을 정확히 같다:

지 여부를 나타내는 관리되지 않는 방법이 있는 retval 반환 값은 직접 번역하거나 여부 retval 반환 값은 자동으로 변환하여 예외가 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top