fischermx
asked on
From C++ to Delphi: several approaches to deal with pointer parameters
I'm writing a piece of code that will interact with a 3rd party C++ library.
In a particular function, for example, the header and function looks like this:
(There are several dozens funcions to call)
SOME_API int CPP_GetSomeValue(int* valueRet);
The function is defined like this:
Then the function it calls, is defined like this:
and finally SomeVal is defined like this:
Now, in Delphi, I have my header defined like this:
CPP_GetSomeValue: function (valueRet: PInteger): Integer stdcall;
And finally how should I define and send and get this value back which was filled by the C++
Library?
I found 3 ways to do the same, but I want to know what's the correct way to do it, what are the
difference between them, and possible problems:
1)
The easiest one, just declare an Integer, pass the address, read the value again.
.. though I feel this "risky", doesn't seem safe. but I don't know
2)
Define a PInteger, New it, pass it, derreference it and dispose it
3)
Define a PInteger, but don't initialize it and pass the address:
This also looks weird, like I'm just using the pointer to get the integer back.
Which one is the correct? The one that doesn't get me memory leaks, dangling pointers and ugly stuff like that.
In a particular function, for example, the header and function looks like this:
(There are several dozens funcions to call)
SOME_API int CPP_GetSomeValue(int* valueRet);
The function is defined like this:
int CPP_GetSomeValue(int* valueRet);
{
GetSomeValue(valueRet);
return 0;
}
Then the function it calls, is defined like this:
int GetSomeValue(int* valueRet)
{
int val;
SomeVal(val)
*valueRet = val;
return 0;
}
and finally SomeVal is defined like this:
int SomeVal(int& typeRet)
{
typeRet = 255;
return 0;
}
Now, in Delphi, I have my header defined like this:
CPP_GetSomeValue: function (valueRet: PInteger): Integer stdcall;
And finally how should I define and send and get this value back which was filled by the C++
Library?
I found 3 ways to do the same, but I want to know what's the correct way to do it, what are the
difference between them, and possible problems:
1)
The easiest one, just declare an Integer, pass the address, read the value again.
ivalueRet : Integer;
CPP_GetSomeValue(@ivalueRet);
Result := ivalueRet;
.. though I feel this "risky", doesn't seem safe. but I don't know
2)
Define a PInteger, New it, pass it, derreference it and dispose it
pvalueRet : Pinteger;
New(pvalueRet);
CPP_GetSomeValue(pvalueRet);
Result := pvalueRet^;
Dispose(pvalueRet);
(I found this also works to get the value: Result := PInteger(@pvalueRet)^;)3)
Define a PInteger, but don't initialize it and pass the address:
pvalueRet : Pinteger;
// Not "new", not "dispose"
CPP_GetSomeValue(@pvalueRet);
Result := Integer(pvalueRet);
(I found this also works to get the value: Result := PInteger(@pvalueRet)^;)This also looks weird, like I'm just using the pointer to get the integer back.
Which one is the correct? The one that doesn't get me memory leaks, dangling pointers and ugly stuff like that.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Right, its unlikely that this is what is causing the AV.
Why don't you run the program with debug options enabled, then set a break point where you suspect the AV happens then you can step through the code until you get the AV
ASKER
Yes, I did that.
The AV occurs in an assignment to true to a boolean member of TDataset that is only used as a simple flag... weird, very weird. Memory has been severely damaged.
I've just found out yesterday that the problem only exists when a DBGrid is present. If I just put DBEdit my dataset works fine.
I know a DBGrid causes a lot of "motion" inside the dataset, and somehow, some thing is getting overriden :(
The AV occurs in an assignment to true to a boolean member of TDataset that is only used as a simple flag... weird, very weird. Memory has been severely damaged.
I've just found out yesterday that the problem only exists when a DBGrid is present. If I just put DBEdit my dataset works fine.
I know a DBGrid causes a lot of "motion" inside the dataset, and somehow, some thing is getting overriden :(
ASKER
Ewangoya:
Let me ask you something more.
According to what you see in the C++ code and the way I'm calling it from Delphi... should the header be declared in Delphi as "stdcall" or "cdecl"?
Let me ask you something more.
According to what you see in the C++ code and the way I'm calling it from Delphi... should the header be declared in Delphi as "stdcall" or "cdecl"?
That should be stdcall
ASKER
Hi, Ewangoya:
The AV I was talking about were fixed by changing "stdcall", as I had it, to "cdecl" !
I'm not understand why.
Well, this is was an additional question anyway, thanks for the answer on the parameter handling.
The AV I was talking about were fixed by changing "stdcall", as I had it, to "cdecl" !
I'm not understand why.
Well, this is was an additional question anyway, thanks for the answer on the parameter handling.
ASKER
Great! Thank you!
ASKER
Thanks for your reply.
I was using method 1 and 2 in different parts of this project (I'm implementing a dataset for a proprietary data format), but currently I'm getting weird AV's inside DB unit, so I was about to blame either of those for trashing Delphi memory and wanted to decide for one.
I guess the AV in my code are not related to these calls.