Jump to content
wuwuxin

How to "correctly" pass an array to a C function

Recommended Posts

I have a C DLL function,

void FillArray(int* data, int num_element);

 

from Delphi side,  is the following caller code correct? 

 

var data: TArray<Integer>;
SetLength(data, 100);
FillArray(data, 100);

 Also, what would be the correct Delphi translation of the C function? Is the following correct?  Should I use "const" or not?

procedure FillArray(const data: TArray<Integer>; num_element: Integer);

 

Edited by wuwuxin

Share this post


Link to post

You need to specify the calling convention, probably cdecl. And I'd declare it as PInteger and pass Pointer(data). 

Edited by David Heffernan

Share this post


Link to post
Guest
1 hour ago, wuwuxin said:

FillArray(data, 100);

Should be

FillArray(data, 100 * SizeOf(Integer));

And you can use const or var with the same result in this case, As David pointed to declare the function with PInteger and pass it by PInteger(@data[0]).

Share this post


Link to post
1 hour ago, Kas Ob. said:

As David pointed to declare the function with PInteger and pass it by PInteger(@data[0]).

The reason I prefer Pointer(data) is that it doesn't trigger range check error if the array has length 0.

  • Thanks 1

Share this post


Link to post

Thank you very much for the advice.

 

1 minute ago, David Heffernan said:

The reason I prefer Pointer(data) is that it doesn't trigger range check error if the array has length 0.

 

Share this post


Link to post
Guest
8 minutes ago, David Heffernan said:

The reason I prefer Pointer(data) is that it doesn't trigger range check error if the array has length 0.

You are totally right there, but i prefer sometimes to trigger it explicitly (in development) to make sure (in similar case to this as with an external API) that the called function is well equipped to handle such case, in other words to make sure i am not leaving it unhandled and unchecked, just as safe measure.

Share this post


Link to post
1 hour ago, Kas Ob. said:

You are totally right there, but i prefer sometimes to trigger it explicitly (in development) to make sure (in similar case to this as with an external API) that the called function is well equipped to handle such case, in other words to make sure i am not leaving it unhandled and unchecked, just as safe measure.

Your way makes it impossible to pass an empty array. If an empty array is never valid, then fine. If an empty array is supported then the Pointer cast is preferable. 

Share this post


Link to post
Guest
33 minutes ago, David Heffernan said:

Your way makes it impossible to pass an empty array. If an empty array is never valid, then fine. If an empty array is supported then the Pointer cast is preferable. 

Right, but i am talking about this case in general, see, it is very rare to design your own code where you need to pass TArray (or any other defined indexed type) to a function with "pointer to array" with element length, most likely the destination belongs to another realm or simply put belongs to a code by different coder (or library), and on same side in cases other than the above example where length established locally, the length might be 0, in this case i prefer to have a nice overflow exception instead of unpredicted behaviour in case i missed explicitly a check against 0 length.

 

It is just personal point of view, in many cases i prefer the compiler checks, unless performance is priority to consider.

Share this post


Link to post
23 hours ago, Kas Ob. said:

Should be


FillArray(data, 100 * SizeOf(Integer));

Why?  The C code clearly names the parameter "num_elements", so it stands to reason that it expects an "element count", not a "byte count".

23 hours ago, Kas Ob. said:

As David pointed to declare the function with PInteger and pass it by PInteger(@data[0]).

A dynamic array is already a pointer, so you don't need to index into the array, PInteger(data) will suffice.

  • Like 1

Share this post


Link to post
Guest
14 minutes ago, Remy Lebeau said:

Why?  The C code clearly names the parameter "num_elements", so it stands to reason that it expects an "element count", not a "byte count".

I missed that with FillChar, you are right there.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×