tags:

views:

171

answers:

4
+1  Q: 

Delphi call a DLL

I have a DLL and wan't 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)

+1  A: 

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].

Mason Wheeler
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
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`.
Rob Kennedy
A: 

Could someone post a complete function declaration with proper calling params ?

Thanks !

benjamin
Are you the one who asked the question? Please remember to log in with the same credentials you used before. Regardless, how is anyone supposed to demonstrate how to call this function? We have no idea where it's from or what it's supposed to do. If you know, then go check the documentation.
Rob Kennedy
No I'm not, but we have the very same problem here :)Thank you very much for the answer. Will try it now !
benjamin
Regarding the calling params, they could by passed as reference and accepted in one way or passed as value and 'accepted' with 'var' or 'out', or even pointer. That's why I asked for the way of passing the parameters. Thanks.
benjamin
I'm unable to make VPN connection, so it'll be the first thing to do in the morning! 'Wonder if it works.. I'll let you know.
benjamin
The parameters should be passed by value or by reference according to how they're declared in the C++, C#, and Delphi declarations shown above. You don't get much leeway there. If you have documentation for this function, then I urge you to post a *new* question about how to call the function; include a link to the documentation, or at least tell everyone what product this function belongs to. "API.dll" isn't helpful at all.
Rob Kennedy
+2  A: 

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;
otherchirps
Agreed on the meaning of the `buffer` parameter, +1. But maybe you mean "cue" not "queue"?
mghie
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.
Mason Wheeler
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.
Rob Kennedy
@mghie - lol, thanks. fixed.
otherchirps
A: 

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.

benjamin
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?
otherchirps
Actually, there's no other reason for redefining PByte except to be more clear for reading it and c/p here.
benjamin