Delphi 的 64 位 DLL c/c++ 接口

Posted

技术标签:

【中文标题】Delphi 的 64 位 DLL c/c++ 接口【英文标题】:64 bits DLL c/c++ interface to Delphi 【发布时间】:2021-06-12 17:14:57 【问题描述】:

我有一个 .h 文件,我需要将其翻译成 Delphi,以调用用 C/C++ 编写的 DLL 接口。

在 32 位中,一切顺利,我可以毫无问题地将 DLL 与 Delphi 应用程序一起使用。

在 64 位中,它不能很好地工作。

这个DLL接口不是我写的,它来自做硬件的第三方。

namespace gXusb 
    
typedef int            INTEGER;
typedef short          INT16;
typedef unsigned       CARDINAL;
typedef unsigned char  CARD8;
typedef float          REAL;
typedef double         LONGREAL;
typedef char           CHAR;
typedef unsigned char  BOOLEAN;
typedef void *         ADDRESS;
    
struct CCamera;
    
extern "C" EXPORT_ void __cdecl Enumerate( void (__cdecl *CallbackProc)(CARDINAL) );
extern "C" EXPORT_ CCamera *__cdecl Initialize( CARDINAL Id );

Cardinal 在 64 位下还是 32 位无符号吗?

我不太确定这种声明此函数类型的方式以及它对 64 位编译的作用:

void (__cdecl *CallbackProc)(CARDINAL)

看起来有点麻烦。

让我困惑的是:

typedef unsigned       CARDINAL;

我发现这是 32 位的 32 位 DLL,但它在 64 位 DLL 下是否保持 32 位?

【问题讨论】:

这能回答你的问题吗? What does the C++ standard state the size of int, long type to be? 您是否尝试混合搭配 32 位和 64 位 exe 和 DLL,因为这不起作用? 这个DLL接口有点奇怪,不是我写的。 "您是否尝试混合匹配 32 位和 64 位 exe 和 DLL,因为这不起作用?-" -> 不,我的 exe 是 64 位的,并且DLL 也是 64 位 unsigned 表示unsigned int,其大小与int 相同(大多数编译器为32 位)。 【参考方案1】:

类似下面的东西应该在 32 位和 64 位都可以正常工作:

unit gXusb;

interface

type
  // prefixing types that Delphi already declares...
  _INTEGER = Int32;
  _INT16 = Int16;
  _CARDINAL = UInt32;
  CARD8 = UInt8;
  _REAL = Single;
  LONGREAL = Double;
  _CHAR = AnsiChar;
  _BOOLEAN = ByteBool;
  ADDRESS = Pointer;

  CCamera = record end;
  PCCamera = ^CCamera;

  UsbEnumCallback = procedure(Param: _CARDINAL); cdecl;

procedure Enumerate(Cb: UsbEnumCallback); cdecl;
function Initialize(Id: _CARDINAL): PCCamera; cdecl;

implementation

const
  TheDLLName = 'the.dll';

procedure Enumerate; external TheDLLName;
function Initialize; external TheDLLName;

end.

就我个人而言,我会去掉任何不是绝对必要的类型别名,使用本机 Delphi 类型是合适的,例如:

unit gXusb;

interface

type
  CARD8 = UInt8;

  CCamera = record end;
  PCCamera = ^CCamera;

  UsbEnumCallback = procedure(Param: UInt32); cdecl;

procedure Enumerate(Cb: UsbEnumCallback); cdecl;
function Initialize(Id: UInt32): PCCamera; cdecl;

implementation

const
  TheDLLName = 'the.dll';

procedure Enumerate; external TheDLLName;
function Initialize; external TheDLLName;

end.

【讨论】:

有人告诉我,Windows 在 64 位模式下仅使用一个调用约定——_stdcall,而不管修饰符如何(在 64 位 Windows 中会忽略 _cdecl 等)。我认为 delphi 只是忽略它们? 是的,有single calling convention on 64bit,但不是stdcall

以上是关于Delphi 的 64 位 DLL c/c++ 接口的主要内容,如果未能解决你的问题,请参考以下文章

64位进程调用32位dll的解决方法

64位win7安装了64位的Oracle11g,用delphi7配置BDE出现下面的问题。

将 32 位 COM DLL 注册到 64 位 Windows 7

从 64 位应用程序加载/与 vb6 COM dll 交互

Delphi - 使用转发导出创建 DLL

DELPHI调用DLL时的回调函数问题