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

Time:08-12

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?

CodePudding user response:

C has a struct called va_list. Args should point to a instance. I don't know much about delphi, but you can write a function in C, that returns a va_list and use it as the args argument. You may need to allocate it instead of using the normal stack allocation of a va_list.

CodePudding user response:

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;
  • Related