我在Delphi中写了.pas 32bit DLL接口,如下所示:
的用途:
{$IFDEF WIN32}
Windows;
{$ELSE}
Wintypes, WinProcs;
{$ENIF}
接口:
function PI_InterfaceSetupDlg(const szRegKeyName: PChar): LongInt cdecl {$IFDEF WIN32} stdcall {$ENDIF};
实现:
function PI_InterfaceSetupDlg; external 'PI_GCS2_DLL.DLL';
它可以在32位Widnows上运行,但是我必须为64位写这样的东西,我有64位dll,但我不知道它必须使用哪些Windows组件以及如何为64位声明函数。 64位Windows是否使用stdcall?我必须使用什么样的变量?
对不起混乱的帖子,我是Stack的新手。
答案 0 :(得分:8)
tl; dr 您的主要问题是您将16位文本传递给期望8位文本的函数,因为您已升级Delphi并且PChar
的含义已更改。 / p>
首先,您可以忘记WinTypes
和WinProcs
。这些可以追溯到16位Delphi。您肯定没有在Delphi 1上进行编译,因此请将第一个代码块更改为:
uses
Windows;
在32位Windows上,有多种可用的调用约定。 Delphi支持stdcall
,cdecl
,register
和safecall
。其中safecall
用于COM,register
是基于Delphi特定寄存器的调用约定。因此,对于互操作,选择归结为stdcall
和cdecl
。
在64位Windows上,只有一个调用约定,编译器只是忽略了您调用约定的任何规范。如果您的32位代码使用cdecl
,则该函数的声明应为:
function PI_InterfaceSetupDlg(szRegKeyName: PChar): LongInt; cdecl;
此声明可用于32位和64位版本。编译64位时,编译器会忽略cdecl
。
同样,如果32位代码使用stdcall
,则声明应为:
function PI_InterfaceSetupDlg(szRegKeyName: PChar): LongInt; stdcall;
您应该记住的一个目标是,您应该努力不需要条件代码来切换32位和64位之间的行为。 64位Windows和Delphi 64位编译器的设计经过深思熟虑,这个目标是可以实现的。
绝大多数数据类型在32位和64位上完全相同。例如,Integer
是两个平台上的带符号32位整数。指针明显不同,但语义完全相同。因此,如果在32位上使用PChar
,则在64位上也使用PChar
。
不同平台之间差异很大的一种类型是NativeInt
。它在32位上为32位宽,在64位上为64位宽。其无符号对应NativeUInt
的行为方式相同。这些类型名称很差。它们实际上只是指针大小的整数,在我看来,应该命名为IntPtr
和UIntPtr
。这些类型通常用于声明句柄。这是表示不透明指针的整数类型。您可能会发现NativeInt
用于Windows句柄类型。这不是声明这些类型的唯一方法,而且很容易认为type Pointer
会是更好的选择。
如果您想了解互操作如何与32位和64位平台进行交互,请阅读Windows
单元。你会在那里找到很少的条件代码。
PI_InterfaceSetupDlg
的网络搜索显示了这一点:
long PI_FUNC_DECL PI_InterfaceSetupDlg(const char* szRegKeyName);
这意味着该函数接受8位文本。在您的Delphi版本(包含64位编译器的版本)中,PChar
是PWideChar
的别名。这是16位文本。所以你需要明确并使用PAnsiChar
。因此,尽管您声明您的代码在32位下运行,但事实并非如此。我的猜测是你最初在旧版本的Delphi上开发了代码,其中PChar
是PAnsiChar
的别名。
至于调用约定,您需要了解PI_FUNC_DECL
如何扩展。它在这里定义:
#ifdef WIN32
#undef PI_FUNC_DECL
#ifdef PI_GCS2_DLL_STATIC
#define PI_FUNC_DECL WINAPI
#else
#ifdef PI_DLL_EXPORTS
#ifndef UNKNOWN_GCS_DLL
#define PI_FUNC_DECL __declspec(dllexport) WINAPI
#else
#define PI_FUNC_DECL WINAPI
#endif
#else
#define PI_FUNC_DECL __declspec(dllimport) WINAPI
#endif
#endif
#else
#define PI_FUNC_DECL
#endif
可以看出,在Windows上,调用约定为WINAPI
,这是一个扩展为__stdcall
的宏。因此,最终的Delphi声明是:
function PI_InterfaceSetupDlg(szRegKeyName: PAnsiChar): Longint; stdcall;
现在您的主要问题是让您的代码与您要迁移到的Delphi的Unicode感知版本一起使用。您面临的主要问题是您的代码尚未移植到Unicode Delphi。在32位编译器下执行此操作。一旦你有了这个工作,切换到64位应该是微不足道的,并且根本不涉及代码更改。