Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>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.</p> <p>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.</p> <p>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.</p> <pre><code>{$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. </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload