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:
int CPP_GetSomeValue(int* valueRet);
{
  GetSomeValue(valueRet);
  return 0;
}

Open in new window


Then the function it calls, is defined like this:
int GetSomeValue(int* valueRet)
{
  int val;
  SomeVal(val)
  *valueRet = val;
  return 0;
}

Open in new window


and finally SomeVal is defined like this:
int SomeVal(int& typeRet)
{
  typeRet = 255;	
  return 0;
}

Open in new window



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;

Open in new window


.. 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);

Open in new window

(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);

Open in new window

(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.

LVL 1
fischermxAsked:
Who is Participating?
 
Ephraim WangoyaConnect With a Mentor Commented:

1.
The first method is the best, clear short and simple
CPP_GetSomeValue(@ivalueRet)
You are passing the address of the variable which is what is expected by the function. This is the method I would use.

2.
This method is also correct but not so user friendly. You allocate memory when you do not need to. You could have simplified this by pointing to an existing variable eg
var
  valueRet: Integer;
  pvalueRet : Pinteger
begin
  pvalueRet := @valueRet;
  CPP_GetSomeValue(pvalueRet);
  Result := valueRet;
end;

But this are just extra steps that make your code less readable

3.
Simply don't use this method


0
 
fischermxAuthor Commented:
Hi, Ewangoya:

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.

0
 
Ephraim WangoyaCommented:

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
0
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
fischermxAuthor Commented:
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 :(

0
 
fischermxAuthor Commented:
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"?
0
 
Ephraim WangoyaCommented:
That should be stdcall
0
 
fischermxAuthor Commented:
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.
0
 
fischermxAuthor Commented:
Great! Thank you!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.