When dynamically loading a DLL where DoSomething
is a method type variable we can do
DoSomething:= GetProcAddress(MyDLLHandle ,'DoSomething');
or
@DoSomething:= GetProcAddress(MyDLLHandle ,'DoSomething');
Both of these seem to behave identically in modern versions of Delphi. My question is - has the @
operator always been optional and, if not, in which version of Delphi did it become optional?
The documentation states that @
, when used with routine (function/procedure) types returns the entry point of the function with type Pointer
. When using the variable directly it naturally has whatever specific type it was declared with but also returns the entry point to the method. GetProcAddress
returns a Pointer
so I'm assuming that the habit of including @
when loading a DLL comes from a time when these mismatched types were not assignment compatible. Is this the case?
Are there any reasonable arguments to prefer either of these styles?
I don't believe that anything has changed since the original versions of Delphi.
The official header translation for GetProcAddress
has a return type of FARPROC
which is an alias to the untyped Pointer
type. Because of this, you can put pretty much anything pointer-esque on the left hand side of the assignment statement, because type checking is suspended when one of the operands is Pointer
.
On the other hand, consider this program:
var
Proc: procedure;
Ptr: Pointer;
begin
Ptr := Proc;
end.
This fails to compile with:
E2010 Incompatible types: 'Pointer' and 'procedure, untyped pointer or untyped parameter'
The simple fix is to use the @
operator:
var
Proc: procedure;
Ptr: Pointer;
begin
Ptr := @Proc;
end.
It is certainly the case that many Delphi examples use:
@Proc := GetProcAddress(...);
rather than
Proc := GetProcAddress(...);
I rather suspect that there is nothing deep here. Just a case of a choice made by the author of one of the first online articles on the subject propagating throughout history with no good reason. Which reminds me of the terrible Rosetta code example of dynamic loading that tests whether an HMODULE
is greater than 32, an erroneous check that can be seen in Stack Overflow questions on a weekly basis!
Should you use @
in these circumstances or not? In my view you should not. It doesn't make much difference, and given that why bother with a needless piece of punctuation?
There is one other scenario that I know where you need to use @
, and in that case you actually need @@
. Consider the following program:
{$APPTYPE CONSOLE}
uses
SysUtils;
var
Proc: procedure;
Ptr: Pointer;
begin
Ptr := @Proc;
Writeln(Format('%p', [Ptr]));
Ptr := @@Proc;
Writeln(Format('%p', [Ptr]));
Readln;
end.
Output
00000000 00423EBC
The first assignment gets the value held in the Proc
variable, which because it is a default initialised global, is zero. The second assignment gets the address of the Proc
variable. And for that you need @@
. It's pretty unusual to need this much indirection, but it tends to crop up when writing code related to dynamic linking.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With