Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 80497
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 10, 20262026-05-10T21:18:43+00:00 2026-05-10T21:18:43+00:00

Normally, in Delphi one would declare a function with a variable number of arguments

  • 0

Normally, in Delphi one would declare a function with a variable number of arguments using the ‘array of const’ method. However, for compatibility with code written in C, there’s an much-unknown ‘varargs’ directive that can be added to a function declaration (I learned this while reading Rudy’s excellent ‘Pitfalls of convering‘ document).

As an example, one could have a function in C, declared like this :

void printf(const char *fmt, ...) 

In Delphi, this would become :

procedure printf(const fmt: PChar); varargs; 

My question is : How can I get to the contents of the stack when implementing a method which is defined with the ‘varargs’ directive?

I would expect that some tooling for this exists, like Dephi translations of the va_start(), va_arg() and va_end() functions, but I can’t find this anywhere.

Please help!

PS: Please don’t drift off in discussions about the ‘why’ or the ‘array of const’ alternative – I need this to write C-like patches for functions inside Xbox games (see the Delphi Xbox emulator project ‘Dxbx’ on sourceforge for details).

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. 2026-05-10T21:18:44+00:00Added an answer on May 10, 2026 at 9:18 pm

    OK, I see the clarification in your question to mean that you need to implement a C import in Delphi. In that case, you need to implement varargs yourself.

    The basic knowledge needed is the C calling convention on the x86: the stack grows downwards, and C pushes arguments from right to left. Thus, a pointer to the last declared argument, after it is incremented by the size of the last declared argument, will point to the tail argument list. From then, it’s simply a matter of reading the argument out and incrementing the pointer by an appropriate size to move deeper into the stack. The x86 stack in 32-bit mode is 4-byte aligned generally, and this also means that bytes and words are passed as 32-bit integers.

    Anyhow, here’s a helper record in a demo program that shows how to read out data. Note that Delphi seems to be passing Extended types in a very odd way; however, you likely won’t have to worry about that, as 10-byte floats aren’t generally widely used in C, and aren’t even implemented in the latest MS C, IIRC.

    {$apptype console}  type     TArgPtr = record   private     FArgPtr: PByte;     class function Align(Ptr: Pointer; Align: Integer): Pointer; static;   public     constructor Create(LastArg: Pointer; Size: Integer);     // Read bytes, signed words etc. using Int32     // Make an unsigned version if necessary.     function ReadInt32: Integer;     // Exact floating-point semantics depend on C compiler.     // Delphi compiler passes Extended as 10-byte float; most C     // compilers pass all floating-point values as 8-byte floats.     function ReadDouble: Double;     function ReadExtended: Extended;     function ReadPChar: PChar;     procedure ReadArg(var Arg; Size: Integer);   end;  constructor TArgPtr.Create(LastArg: Pointer; Size: Integer); begin   FArgPtr := LastArg;   // 32-bit x86 stack is generally 4-byte aligned   FArgPtr := Align(FArgPtr + Size, 4); end;  class function TArgPtr.Align(Ptr: Pointer; Align: Integer): Pointer; begin   Integer(Result) := (Integer(Ptr) + Align - 1) and not (Align - 1); end;  function TArgPtr.ReadInt32: Integer; begin   ReadArg(Result, SizeOf(Integer)); end;  function TArgPtr.ReadDouble: Double; begin   ReadArg(Result, SizeOf(Double)); end;  function TArgPtr.ReadExtended: Extended; begin   ReadArg(Result, SizeOf(Extended)); end;  function TArgPtr.ReadPChar: PChar; begin   ReadArg(Result, SizeOf(PChar)); end;  procedure TArgPtr.ReadArg(var Arg; Size: Integer); begin   Move(FArgPtr^, Arg, Size);   FArgPtr := Align(FArgPtr + Size, 4); end;  procedure Dump(const types: string); cdecl; var   ap: TArgPtr;   cp: PChar; begin   cp := PChar(types);   ap := TArgPtr.Create(@types, SizeOf(string));   while True do   begin     case cp^ of       #0:        begin         Writeln;         Exit;       end;        'i': Write(ap.ReadInt32, ' ');       'd': Write(ap.ReadDouble, ' ');       'e': Write(ap.ReadExtended, ' ');       's': Write(ap.ReadPChar, ' ');     else       Writeln('Unknown format');       Exit;     end;     Inc(cp);   end; end;  type   PDump = procedure(const types: string) cdecl varargs; var   MyDump: PDump;  function AsDouble(e: Extended): Double; begin   Result := e; end;  function AsSingle(e: Extended): Single; begin   Result := e; end;  procedure Go; begin   MyDump := @Dump;    MyDump('iii', 10, 20, 30);   MyDump('sss', 'foo', 'bar', 'baz');    // Looks like Delphi passes Extended in byte-aligned   // stack offset, very strange; thus this doesn't work.   MyDump('e', 2.0);   // These two are more reliable.   MyDump('d', AsDouble(2));   // Singles passed as 8-byte floats.   MyDump('d', AsSingle(2)); end;  begin   Go; end. 
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 110k
  • Answers 110k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer apple does not provide api's for deleting photos from the… May 11, 2026 at 9:32 pm
  • Editorial Team
    Editorial Team added an answer Refer to the specifications. Here's a basic implementation: public static… May 11, 2026 at 9:32 pm
  • Editorial Team
    Editorial Team added an answer This would probably get a better answer at serverfault.com. I'm… May 11, 2026 at 9:32 pm

Related Questions

I was getting advice from Rob Kennedy and one of his suggestions that greatly
There is a post by Raymond Chen, where he tells how bad IsBadXxxPtr function
Normally, I run Linux in a VM, however, most of my VMs are on
Normally using a variable in a .cpp file results in the variable being globally

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.