• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 239
  • Last Modified:

API conversion questions

I am having issues with some API conversions.  Probably the biggest problem is that I don't really know C all that well.

For the most part I manage to bumble my way through, but there's one thing that I just don't know how to translate - variable number of parameters.

When in the C declaration you get something like...

int somefunction(int param_count, ...)

...how does this translate into Delphi?
  • 5
  • 3
  • 2
  • +3
1 Solution
Hi Hamlet it has been a while. How have you been doing?

Don't know it this help you any but I cheat and look in the Windows.pas file and look for the function I am trying to use and see how Delphi has it setup.

Like this one
function GetFileInformationByHandle(hFile: THandle; var lpFileInformation: TByHandleFileInformation): BOOL; stdcall;

Which in the SDK it is listed like this
BOOL GetFileInformationByHandle(

    HANDLE hFile,      // handle of file
    LPBY_HANDLE_FILE_INFORMATION lpFileInformation      // address of structure

A lot of times this helps me break it down faster and code it using Delphi Syntax

The Crazy One
Somtimes the syntax is similar between the two but quite often they are not. So when I check the Windows.pas I can see what Delphi expects to be passed as the parameters.
Hi Hamlet,

if your function in C is like,
int somefunction(int param, char *test, float &c);

the same function in delphi is:

function somefunction(var param: integer; test: string; c: real): integer;

I think is this,

Train for your Pen Testing Engineer Certification

Enroll today in this bundle of courses to gain experience in the logistics of pen testing, Linux fundamentals, vulnerability assessments, detecting live systems, and more! This series, valued at $3,000, is free for Premium members, Team Accounts, and Qualified Experts.

function somefunction(param_count: Integer): Integer;
oops, everyone... sorry, didn't refresh the page :)
Hamlet081299Author Commented:
Hi.  Yeah, took some time out from the computer scene.
I too often look at windows API translations, but in the Windows API they avoid the variable number of parameters.

Thanks for the suggestions, but I know how to translate when the parameters are fixed.  In C though you can specify a function that has a variable number of parameters.  This is what the "..." indicates.

(n example of a C function that uses this is "printf", if that helps)
... means variable argument count (what cdecl is for).
It is not directly convertible to Pascal.
You will often find a second function with a parameter of va_list type. That one is convertible with a glue function.
Have a look at the Java Native Interface conversion over at http://delphi-jedi.org/APILIBRARY
Hamlet081299Author Commented:
Thanks.  Unfortunately the person who wrote the dll did not consider this as the dll was only intended to be called from C.

I think my only option may be to use some embedded assembler to do the calling.  That way I can push all the necessary arguments one by one.

The other thing I tried was to translate ...
  int somefunction(int param_count, ...)
... as ...
  function somefunction(param_count: integer; p1, p2, p3, p4, p5, p6, p7, p8, p9, p10: pointer); cdecl;

... and then just pass nil for the unneeded parameters.  It actually seems to work okay, and I think because of the cdecl calling convention it is not doing anything nasty to the stack.
Hamlet081299Author Commented:
(slight improvement) I changed p1..p10 to have defaults of nil so I don't have to specify them
you can also do

function somefunction(var somename): someresult;

and it will actually be passed as pointer.

As for the variable number of variables, nope, Pascal can't do it... you can, of course, get round it using arrays, if suitable... eg.

function GetLargestNumber(Numbers: array of Integer): Integer;
  i: Integer;
  if Length(Numbers) = 0 then
    raise Exception.Create('Cannot pass empty array!');
  Result := Numbers[Low(Numbers)];
  for i := Low(Numbers) to High(Numbers) do
    if Numbers[i] > Result then
      Result := Numbers[i];

and you call it as follows:

MyLargestNumber := GetLargestNumber([0, 1, 43, 65, 324, 76, 54]);
Hamlet081299Author Commented:
DragonSlayer - thanks, but the main point was to translate an existing API (from a dll written in C).  I've decided for now to stick with having the fixed number of defined parameters (which works), and may later try to wrap the API using some embedded assembly.

As sometimes happens I post a question here to try to get some ideas, but then largely solve the problem myself anyway (sigh).

If someone wants to give me a rough sample of asm code that'd push parameters from an "array of const" onto the stack and then call a stripped down version of the API then I'll award them the points.
Hamlet081299Author Commented:
Time for a tidy up.

I think the best answer to this question was what I came up with myself.

Passing a defined large number of parameters to the function seesm to behave correctly.  It's not ideal, but in the end I allowed up to 20 parameters all with "nil" defaults so I'm happy with that.

I'll get CS to close this question.  Thanks to those who took the time to respond.
PAQ'd and 100 points refunded


Community Support Moderator
Experts Exchange
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.

Join & Write a Comment

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

  • 5
  • 3
  • 2
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now