4

我在回调函数中遇到程序崩溃(用 Delphi 6 编写)的问题。该函数中的该函数没有任何问题,因为它在其他地方使用,并且我有一个跟踪语句作为该函数中获取输出的最后一行。我想知道我的界面是否有问题。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声明看起来正确吗?

他们是正确的,只有一个例外。这两种回调函数类型的调用约定不正确。在 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 编译器定义。你不需要定义它。

我希望 IFDEF 存在,因为 Bob 博士的转换器最初针对 16 位 Delphi 1。在 16 位 Windows 上,默认的 Windows 调用约定是早已被遗忘的 pascal 调用约定。IFDEF 现在是一个遗物,您可以将其删除。但自然而然地保留标准调用。

我从来没有对自动标题​​翻译器感到非常满意。就个人而言,我认为您可能会更好地手动完成。

于 2012-08-27T06:40:01.743 回答