gpt4 book ai didi

delphi - @映射方法入口点时的运算符用法

转载 作者:行者123 更新时间:2023-12-03 14:53:33 25 4
gpt4 key购买 nike

当动态加载 DLL 时,其中 DoSomething 是我们可以执行的方法类型变量

 DoSomething:= GetProcAddress(MyDLLHandle ,'DoSomething');

 @DoSomething:= GetProcAddress(MyDLLHandle ,'DoSomething');

这两者在现代版本的 Delphi 中似乎表现相同。我的问题是 - @ 运算符是否始终是可选的,如果不是,在 Delphi 的哪个版本中它成为可选的?

文档指出,@ 与例程(函数/过程)类型一起使用时,返回类型为 Pointer 的函数的入口点。当直接使用变量时,它自然具有声明时使用的任何特定类型,但也会返回方法的入口点。 GetProcAddress 返回一个 Pointer,所以我假设在加载 DLL 时包含 @ 的习惯来自于这些不匹配的类型还没有出现的时候。分配兼容。是这样吗?

是否有任何合理的理由来支持这两种风格?

最佳答案

我认为自 Delphi 的原始版本以来没有任何改变。

GetProcAddress 的官方 header 翻译具有 FARPROC 返回类型,它是无类型 Pointer 类型的别名。因此,您可以将几乎所有类似指针的内容放在赋值语句的左侧,因为当其中一个操作数是“指针”时,类型检查会暂停。

另一方面,考虑这个程序:

var
Proc: procedure;
Ptr: Pointer;

begin
Ptr := Proc;
end.

编译失败:

E2010 Incompatible types: 'Pointer' and 'procedure, untyped pointer or untyped parameter'

简单的修复方法是使用 @ 运算符:

var
Proc: procedure;
Ptr: Pointer;

begin
Ptr := @Proc;
end.

许多 Delphi 示例都使用这种情况:

@Proc := GetProcAddress(...);

而不是

Proc := GetProcAddress(...);

我相当怀疑这里没有什么深奥的东西。这只是关于该主题的第一篇在线文章的作者在没有充分理由的情况下在整个历史中传播的选择的一个例子。这让我想起了可怕的Rosetta code example动态加载测试 HMODULE 是否大于 32,这是每周都会在 Stack Overflow 问题中看到的错误检查!

在这些情况下您是否应该使用@?在我看来你不应该。这没有多大区别,既然如此,为什么还要费心使用一些不必要的标点符号呢?

据我所知,还有另一种情况需要使用 @,在这种情况下,您实际上需要 @@。考虑以下程序:

{$APPTYPE CONSOLE}

uses
SysUtils;

var
Proc: procedure;
Ptr: Pointer;

begin
Ptr := @Proc;
Writeln(Format('%p', [Ptr]));
Ptr := @@Proc;
Writeln(Format('%p', [Ptr]));
Readln;
end.

输出

0000000000423EBC

第一个赋值获取 Proc 变量中保存的值,因为它是默认初始化的全局变量,所以为零。第二个赋值获取 Proc 变量的地址。为此,您需要@@。需要这么多间接性是很不寻常的,但在编写与动态链接相关的代码时往往会突然出现。

关于delphi - @映射方法入口点时的运算符用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46077994/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com