0

I have a DLL and want to call it from Delphi

extern "C" export_dll_function int RetScreen(int number, char** pbuffer, unsigned long* psize,
IMAGE_RESOLUTION resolution, float zoom, int dx, int dy);


[DllImport("API.DLL", EntryPoint = "_RetScreen")]
public static extern int pRetScreen(int number, ref byte[] pdata, ref long size, int res, float zoom, int dx, int dy);

which delphi type refers to char** pbuffer for the prototype? (it is an image)

3 Answers 3

2

Taking my cue from the C# definition as well as the C version, it looks more like pbuffer is meant to be a pointer to a byte buffer. That is, in delphi it would be better as a PByte, passed by reference. No need to use a PChar when you really want a PByte.

eg.

type     
  IMAGE_RESOLUTION = integer; // judging from the c# parameters...
  float = Single; // 4 bytes...

  TRetScreenFn = function(number: integer;
                          var buffer: PByte;
                          var size: Cardinal;  
                          resolution: IMAGE_RESOLUTION;
                          zoom: float;
                          dx : integer;
                          dy : integer): integer; cdecl; 

(I'm assuming cdecl here from the extern "C" -- might be wrong here, depending on what "export_dll_function" means. If it's not this, it'll probably be stdcall instead.)

If it's possible for nil to be given instead of buffer or size, you won't be able to use "var". In that case, you'd need to do something like this:

type 
  PPByte = ^PByte;
  PCardinal = ^Cardinal;

  TRetScreenFn = function(number: integer;
                          buffer: PPByte;
                          size: PCardinal;  
                          resolution: IMAGE_RESOLUTION;
                          zoom: float;
                          dx : integer;
                          dy : integer): integer; cdecl; 

This is essentially the same thing. Except with the first version, the compiler will enforce the var parameters to be non-nil. This second version, it just sees pointers, and doesn't care.

Then, you know the rest (ignoring sane error checks):

var
  retScreen : TRetScreenFn;
  dll : HMODULE;
begin
  dll := LoadLibrary("API.dll");
  try
    retScreen := TRetScreenFn(GetProcAddress(dll, "RetScreen"));

    // ... call retScreen(); do stuff...
  finally
    CloseHandle(dll);
  end;
end;
3
  • Agreed on the meaning of the buffer parameter, +1. But maybe you mean "cue" not "queue"?
    – mghie
    Commented Nov 25, 2009 at 15:38
  • Not likely. A char** almost always means an array of char*, not a "pointer to a single char*". If this is an image, it's likely that each individual char* represents one scanline (horizontal row of pixels) and that each new scanline doesn't necessarily begin immediately after the last one ended, for memory alignment or similar reasons. Commented Nov 25, 2009 at 17:03
  • 2
    Mason, char** also means "a simple char buffer to be allocated by the called function and returned to the caller." The C# declaration is especially telling in that regard. Commented Nov 25, 2009 at 18:15
1

Jqno's close. A char** is an array of C-strings, but C doesn't do arrays or strings the way Delphi does. The base type here is a PAnsiChar, and you need an unbounded array. Declare it as a PCStringArray, defined like this:

type
  TCStringArray = Array [0..0] of PAnsiChar;
  PCStringArray = ^TCStringArray;

Number is most likely the number of the upper bound to your array. You declare it as [0..0], but the actual size is [0..number - 1].

2
  • 2
    Minor nitpick: A char** isn't an array of C-strings, it is a pointer to a char*. There may be more such pointers in the next memory locations (so they form an array), but one can't tell from the declaration.
    – mghie
    Commented Nov 25, 2009 at 15:27
  • 2
    If it holds an image, then Byte is almost certainly a better choice, as reflected by the C# declaration. The C++ code should have used unsigned char. Commented Nov 25, 2009 at 18:11
0

It works ! Otherchirps, Rob Kennedy, mghie, Mason Wheeler, thank you very much !

For anyone else having the same problem: This is the correct function declaration (see otherchirps's post):

TRetScreenFn = function(number: integer;
                          var buffer: PByte;
                          var size: Cardinal;  
                          resolution: IMAGE_RESOLUTION;
                          zoom: float;
                          dx : integer;
                          dy : integer): integer; stdcall;

(worked with stdcall)

type
  PByte = ^TByte;
  TByte = array of byte;

Called with these parameters: RetScreen(int, buffer: PByte, int, int, float, int, int). Function names inside dll for getting images based on those parameters are: GetImage and GetWindowImageQEx.

Rob Kennedy, I couldn't post more documentation because i don't have it. It's about Arecont's camera DLL (AV2000sdk.dll). Unfortunately, Arecont doesn't allow it's full SDK (for delphi and .net) to be downloaded.

Thanks again.

2
  • Sorry - I'm unclear why you're redefining PByte. This should already be defined for you as one of the "built in" types. It is more like this: type PByte = ^Byte; Byte = 0..255; Is there a reason you're explicitly making it an array type? Commented Nov 30, 2009 at 12:25
  • Actually, there's no other reason for redefining PByte except to be more clear for reading it and c/p here.
    – benjamin
    Commented Nov 30, 2009 at 19:39