用Delphi编写64位接口

用Delphi编写64位接口,delphi,interface,32bit-64bit,Delphi,Interface,32bit 64bit,我在Delphi中编写了.pas 32位DLL接口,如下所示: 用途: 接口: function PI_InterfaceSetupDlg(const szRegKeyName: PChar): LongInt cdecl {$IFDEF WIN32} stdcall {$ENDIF}; 实施: function PI_InterfaceSetupDlg; external 'PI_GCS2_DLL.DLL'; 它可以在32位Widnows上运行,但我必须为64位编写类似的代码,我有64

我在Delphi中编写了.pas 32位DLL接口,如下所示:

用途:

接口:

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?我必须使用什么样的变量


对不起,这篇文章乱七八糟,我是新来的

tl;dr您的主要问题是,您正在将16位文本传递给一个需要8位文本的函数,因为您已升级了Delphi,并且
PChar
的含义已更改


首先,您可以忘记
WinTypes
WinProcs
。这些可以追溯到16位Delphi。您肯定不是在Delphi 1上编译,因此将第一段代码更改为:

uses
  Windows;
在32位Windows上,有多种可用的调用约定。Delphi支持
stdcall
cdecl
寄存器
安全调用
。其中
safecall
用于COM,而
register
是一种基于Delphi特定寄存器的调用约定。因此,对于互操作,可以选择
stdcall
cdecl

在64位Windows上,只有一个调用约定,编译器只会忽略您制定的任何调用约定规范。如果您的32位代码使用
cdecl
,则该函数的声明应为:

function PI_InterfaceSetupDlg(szRegKeyName: PChar): LongInt; cdecl;
function PI_InterfaceSetupDlg(szRegKeyName: PChar): LongInt; stdcall;
此声明可用于32位和64位版本。当编译64位时,
cdecl
被编译器忽略

类似地,如果32位代码使用
stdcall
,则声明应为:

function PI_InterfaceSetupDlg(szRegKeyName: PChar): LongInt; cdecl;
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
。这些类型通常用于声明句柄。这是表示不透明指针的整数类型。您可能会发现用于Windows句柄类型的
nativent
。这不是声明这些类型的唯一方法,而且很容易认为
类型指针
将是一个更好的选择

如果您想了解interop如何与32位和64位平台交互,请阅读
Windows
单元。您将在那里发现很少的条件代码


PI_InterfaceSetupDlg
的Web搜索揭示了以下内容:

long PI_FUNC_DECL PI_InterfaceSetupDlg(const char* szRegKeyName);
这意味着该函数接受8位文本。在您的Delphi版本(包含64位编译器的版本)中,
PChar
PWideChar
的别名。这是16位文本。因此,您需要明确使用
PAnsiChar
。因此,尽管您声明代码在32位以下工作,但事实并非如此。我猜您最初是在旧版本的Delphi上开发代码的,
PChar
PAnsiChar
的别名

至于调用约定,您需要了解如何扩展
PI\u FUNC\u 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
,这是一个扩展到
\uu stdcall
的宏。因此,德尔福的最终声明是:

function PI_InterfaceSetupDlg(szRegKeyName: PAnsiChar): Longint; stdcall;


现在的主要问题是让您的代码与您要迁移到的支持Unicode的Delphi版本一起工作。您面临的主要问题是代码尚未移植到Unicode Delphi。在32位编译器下执行此操作。一旦工作正常,切换到64位应该很简单,而且根本不涉及代码更改。

FWIW,声明
PI_InterfaceSetupDlg
的第一块代码不会编译。你确定你发布了真实的代码吗?是的,它打开窗口选择pc和光学舞台控制器之间的连接接口,但返回带有随机字符的错误对话框。该注释对我来说毫无意义。代码编译时没有警告和错误,因此我认为处理程序大小存在问题。否,问题中的代码没有编译。您的代码可能会编译,但您引入了一个输入错误。真正的问题是,您的代码只有在使用Delphi版本进行编译时才有效,
PChar
PAnsiChar
的别名。但是您现在尝试在Delphi上编译,
PChar
PWideChar
的别名。在担心64位之前,您需要先解决该问题。在处理64位之前,请确保您的代码在32位上是正确的。既然我已经更新了答案,你真的应该更仔细地阅读我的答案;博士,我删除了我的评论。我把Chars改成了AnsiChars,效果很好。谢谢