I'm try to use :
if b<> nil then Enabled := b;
but I can't build it , it will display: E2008 Incompatible types
Pointer variables are ABC of Pascal. http://en.wikipedia.org/wiki/Pascal_(programming_language)#Pointer_types
So the proper way to write that check would be
function Test.get_Param(out a : BOOL): HRESULT; stdcall;
var ptr: ^BOOL;
begin
ptr := @a;
if nil = ptr then ....
a := b;
Result := T_Result;
end;
That is the basic question to you explicit questions.
Now, in reality that check does not help. It would only protect your from nil/NULL pointers, but that is not what probably happens. What happens is probably a random garbage pointer instead of nil. Due to error in the calling code.
Again, you can check that via var ptr: Pointer {untyped}; ptr := @Self; if ptr = nil then ...
or just if nil <> Self
or just if Assigned(Self)
- but that would only protect you from NIL pointers, not from RANDOM GARBAGE pointers.
More so, i think that actual garbage is not in pointer to the variable a
, but to the pointer to Self
and b
being a member of TEST classm, thus the real statement is a := Self.b;
.
Since you use stdcall
i think you're trying to make a DLL for using from an EXE made in a in non-Delphi language. Most probably you either made a wrong definition for function in that client app code. Actually, you just can make a proper declaration is you Test
is a class. You only can make a proper if get_Param
is a method of RECORD Test
or perhaps if it is STATIC CLASS method of Test
class. So the proper way to write your function would be like following
function Test.get_Param(out a : BOOL): HRESULT;
begin
a := b;
Result := T_Result;
end;
function DLL_get_Param(const TestObject: pointer; out a : BOOL): HRESULT; stdcall;
var MyTest: Test;
begin
pointer(MyTest) := TestObject;
Result := MyTest.DLL_get_Param(a);
end;
export DLL_get_Param;
Read Delphi documentation what you can get/put to/from DLL functions.
Integers
, floats
, pointers
, IInterface
. You cannot pass into DLL complex and behaving objects like stings, dynamic arrays, object instances. And since you cannot pass an object instance, you cannot pass a Self
variable and you cannot call a method.
One very expensive way to catch it would be like
{global} var TestInstances: TList;
type
TEST = class...
procedure AfterConstructon; override;
procedure BeforeConstructon; override;
....
procedure Test.AfterConstructon;
begin
inherited;
TestInstances.Add(Self); // single-thread assumption here
end;
procedure Test.BeforeConstructon;
begin
TestInstances.Remove(Self); // single-thread assumption here
inherited;
end;
function Test.get_Param(out a : BOOL): HRESULT; stdcall;
begin
if not ( TestInstances.IndexOf(Self) >= 0 {found!} ) // single-thread assumption here
then ... WTF ???
...
....
initialization
TestInstances := TList.Create;
finalization
TestInstances.Free;
end;
If your DLL can be used by multi-threaded application you should also wrap the marked calls into http://docwiki.embarcadero.com/Libraries/XE2/en/System.SyncObjs.TCriticalSection