Search code examples
cdelphidllvariadic-functions

How can I interface with a C callback definition containing va_args in Delphi?


A C library that I would like to integrate in Delphi contains the following debug log call back function definition:

typedef void (*libfoo_log_cb)(void *data, int level, const char *fmt, va_list args);

The signature of my callback function in Delphi looks like this:

procedure LibFooLog( data: Pointer; level: Integer; fmt: PAnsiChar; args: Pointer ); cdecl;

When the callback function is triggered by the C library the "fmt" string obviously contains a lot of printf specifiers like "%s" etc. How can I assemble the string from "fmt" and the va-list "args" in Delphi? Maybe I can use the MSVCRT run-time of Windows to do the formatting but how would I map the arguments to it?


Solution

  • There is a possibility to let the Windows system's C runtime library do the string formatting. This should work if (and only if) the C library that accepts the callback also is linked to the same C runtime library.

    Example Code:

    function vsnprintf( buffer: PAnsiChar; count: LongWord; format: PAnsiChar; argptr: Pointer ): Integer; cdecl; external 'msvcrt.dll';
    
    procedure LibFooLog( data: Pointer; level: Integer; fmt: PAinsiChar; args: Pointer ); cdecl;
    var
       Buffer: array[0..4096] of AnsiChar;
       Count: Integer;
    begin
       Count := vsnprintf(@Buffer[0], SizeOf(Buffer), fmt, args);
       if Count > 0 then
       begin
          // cast the output to string with AnsiString(Buffer) and do something with it
       end;
    end;