4

コールバック関数で (Delphi 6 で作成された) プログラムがクラッシュするという問題があります。その関数は他の場所で使用されているため、その関数には何も問題はありません。出力を取得する関数の最後の行として trace ステートメントがあります。私が持っているインターフェースに何か問題があるのではないかと思っています。Cヘッダーファイルからの抜粋は...

/*
#ifdef SSLCLIENT_EXPORTS
    #define SSLCLIENT_API __declspec(dllexport)
#else
    #define SSLCLIENT_API __declspec(dllimport)
#endif
*/
#define SSLCLIENT_API
#define CDR_EXPORT CALLBACK

typedef int   CDRHANDLE;
//  The definition of preceding call back functions is as follows:
#define CDR_PRORESS_CONTINUE 0
#define CDR_CANCEL_CONNECTION -1

#define CONNECTION_TERMINATED       1
#define CONNECTION_CLOSED           2

#ifdef __cplusplus
//extern "C" {
#endif

typedef int (CDR_EXPORT *RECEIVEINGFUNC )
(
    char *callData,
    void *applicationData
);

SSLCLIENT_API CDRHANDLE CDR_EXPORT CdrOpenConnection
(
   char             *IPAddressOrMachineName,
   char             *usernameOfCDRUserGroup,
   char             *password,
   RECEIVEINGFUNC    CDRRecord,
   STOPFUNC          CDRStop,
   void             *applicationData
);


#ifdef __cplusplus
//} // extern "C"
#endif
#endif

そして、Drbobs プログラムを使用して Delphi ソースを生成しました...

type
  RECEIVEINGFUNC = function(CallData: PChar; ApplicationData: Pointer): integer;
  STOPFUNC = procedure(StopReason: integer; ApplicationData: Pointer);

(*  = INT (CDR_EXPORT*RECEIVEINGFUNC ) ( CHAR*CALLDATA, VOID*APPLICATIONDATA );
type
  = VOID (CDR_EXPORT*STOPFUNC ) ( INT STOPREASON, VOID*APPLICATIONDATA );
*)

var
  CdrOpenConnection: function(IPAddressOrMachineName: PChar;
                              usernameOfCDRUserGroup: PChar;
                              password: PChar;
                              CDRRecord: RECEIVEINGFUNC;
                              CDRStop: STOPFUNC;
                              applicationData: Pointer): CDRHANDLE cdecl  {$IFDEF WIN32} stdcall {$ENDIF};

そして私には機能があります

function DoCdrRecord1(CallData: PChar; ApplicationData: Pointer): integer;
begin
  try
    // do stuff...
    trace('DoCdrRecord1::back from _HndlCdrRec');
  except
    on e: exception do
    begin
      trace('DoCdrRecord1::exception -> ' + e.message);
    end;
  end
end;

私の質問は...

  1. 上記の Delphi 宣言は正しいですか?
  2. プログラムをコンパイルするときに WIN32 を含める必要がありますか?

プログラムのどこが間違っているのか途方に暮れています。どんな助けでも大歓迎です。

4

2 に答える 2

4

呼び出し規約がありません。

RECEIVEINGFUNCとして定義されCDR_EXPORT、少し上に次のように表示されます。

#define CDR_EXPORT CALLBACK

また、CALLBACK は、Delphi インポートで として定義する必要がありますstdcall; したがって、関数を次のように修正すると、機能するはずです。

function DoCdrRecord1(CallData: PChar; ApplicationData: Pointer): integer; stdcall;
于 2012-08-27T03:46:38.077 に答える
4

1. 上記の Delphi 宣言は正しいですか。

それらは正しいですが、1 つの例外があります。2 つのコールバック関数の型の呼び出し規約が正しくありません。C コードでは、コールバック関数の型は CDR_EXPORT で宣言されており、CDR_EXPORT は CALLBACK として定義されています。これは、Windows ヘッダー ファイルと __stdcall で定義されています。そのため、Delphi 関数の型は一致する必要があります。

RECEIVEINGFUNC = function(CallData: PChar;
    ApplicationData: Pointer): integer; stdcall;
STOPFUNC = procedure(StopReason: integer;
    ApplicationData: Pointer); stdcall;

これが翻訳の唯一の誤りです。

2. プログラムのコンパイル時に WIN32 を含める必要がありますか?

を含めるのではなく、定義することを意味していると思います。ここでは何もする必要はありません。WIN32 条件は、Delphi 6 コンパイラによって定義されます。定義する必要はありません。

Dr. Bob のコンバーターはもともと 16 ビットの Delphi 1 を対象としていたため、IFDEF があることを期待しています。また、16 ビット Windows では、デフォルトの Windows 呼び出し規則は、長い間忘れられていた Pascal 呼び出し規則でした。その IFDEF はレリックになり、削除できます。ただし、当然、stdcall を保持します。

自動ヘッダー トランスレータにそれほど満足したことはありません。個人的には手作りの方がいいと思います。

于 2012-08-27T06:40:01.743 に答える