C语言转Delphi翻译

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

我使用DrBob的程序生成了一个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?

我不知道程序出了什么问题。非常感谢任何帮助。


FreePascal也有一个h2pas转换器。我认为它更现代化一些。我建议你也用这个工具来转换头文件并比较结果,这可能会凸显出问题。 - Arioch 'The
没有一个 C 头文件到 Pascal 文件转换器能够完美地工作,因为它们不是 C 编译器。它们可以完成大部分的解析工作,但总是需要手动干预(特别是因为大多数 C 代码严重依赖于宏扩展)。 - Jeroen Wiert Pluimers
2个回答

4

您缺少调用约定。

RECEIVEINGFUNC被定义为CDR_EXPORT,并且稍微往上看:

#define CDR_EXPORT CALLBACK

并且需要在Delphi的导入中将CALLBACK定义为stdcall;。因此,按照以下方式修复您的函数,应该就能正常工作:

function DoCdrRecord1(CallData: PChar; ApplicationData: Pointer): integer; stdcall;

1
回调函数通常是STDCALL,而不是cdecl(windef.h:#define CALLBACK __stdcall) - MBo
啊,你说得对。很抱歉,那时候太晚了。现在已经修复了。 - Mason Wheeler

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?

我想您的意思是“定义”而不是“包含”。这里无需操作。Delphi 6编译器已经定义了WIN32条件。您无需定义它。

我认为IFDEF之所以存在,是因为Dr.Bob的转换器最初定向于16位Delphi 1。在16位Windows上,默认的Windows调用约定是被深深遗忘的Pascal调用约定。现在该IFDEF已经成为一个遗物,可以删除它。但是,请保留stdcall。

我从来没有对自动头文件翻译器感到非常满意。个人认为,手动翻译可能更好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接