Problems accessing a C++ dll that needs a struct from D7

Posted on 2005-04-19
Last Modified: 2010-04-05
The important .h stuff:

#define MAX_PATH 4096

#ifdef _WIN32
  #pragma pack (push, 1)
  #pragma pack(1)

typedef struct _INFO_FILE
  unsigned long   cbSize;
  char            Path[MAX_PATH];
  char            Mode[8];

typedef struct _INFO_BUFFER
  unsigned long   cbSize;
  void  *         Buffer;
  unsigned long   Size;

typedef struct _INFO_ITEM
  int             Type;
  int             ItemFormat;
    INFO_BUFFER   InfoBuffer;                
    INFO_FILE     InfoFile;

HRESULT WINAPI api_OpenItem                      (IN API_CLID clid, IN INFO_ITEM *info,OUT API_ITEM * item);

This is what I've come up with so far:

  MAX_PATH = 4096;

  PInfo_Buffer = ^TInfo_Buffer;
  TInfo_Buffer = record
    cbsize  : LongWord;
    Buffer  : Pointer;
    Size    : LongWord;

  PInfo_File = ^TInfo_File;
  TInfo_File = record
    cbsize  : LongWord;
    Path    : array[0..MAX_PATH - 1] of Char;
    Mode    : array[0..7] of Char;

  PInfo_Item = ^TInfo_Item;
  TInfo_Item = record
    ItemType   : Integer;
    ItemFormat : Integer;
    case Integer of
      0: (ItemBuffer : TInfo_Buffer);
      1: (ItemFile   : TInfo_File);

function api_OpenItem(
    API_CLID: THandle;      
    InfoItem: PInfo_Item;
    out API_ITEM: THandle    
  ): LongWord;
  stdcall; external 'api.dll';

  engine: THandle;
  item: THandle;

procedure TForm1.Button2Click(Sender: TObject);
  p: TInfo_Item;
  fn: String;                
  r: LongWord;
  fn := edtFileName.Text;
  p.ItemType := API_ITEM_FILE;
  p.ItemFormat := API_ITEM_FORMAT_OTHER;
  p.ItemFile.cbsize := SizeOf(TInfo_File);
  StrPCopy(p.ItemFile.Path, fn);
  StrPCopy(p.ItemFile.Mode, 'rb');
  r := api_OpenItem(engine, @p, item);
  if (r <> API_OK)
  then showmessage('ERROR: ' + inttostr(r))
  else showmessage('success');


The dll simply returns a generic error message. "engine" is assigned (successfully) in an earlier call. I've tried the records both packed and as you see it.

Any help would be greatly appreciated.
Question by:orbit1star
    LVL 26

    Expert Comment

    by:Russell Libby

    Just for future reference, the #pragma pack(1) is an indicator that "packed record" should be used on the record structs (though in this instance the structs are all DWORD aligned anyways).

    Regarding the error though, it appears that engine is never assigned anything before being passed? Is this intentional, or should there be a call to allocate/init/whatever the engine before making the call to api_OpenItem? If not, then you should probably be passing zero to the engine param, or setting engine:=0, as Delphi does not initialize its variables (meaning engine will have whatever is currently in memory at that address).



    Author Comment

    Engine is assigned in an earlier function (I noted that at the bottom ;-) ). I'm pretty sure the engine value is valid - I can make another, different call and get results with the same engine parameter.
    LVL 26

    Expert Comment

    by:Russell Libby

    >"The dll simply returns a generic error message. "engine" is assigned (successfully) in an earlier call. I've tried the records both packed and as you see it.

    Sorry, the wording made it sound like the error message was "engine is assigned..." Btw, what IS the actual message coming back? You might also try to define the api call as:

     PHandle = ^THandle;

    function api_OpenItem(API_CLID: THandle; InfoItem: PInfo_Item; API_ITEM: PHandle): LongWord; stdcall; external 'api.dll';

    and call it with

    api_OpenItem(engine, @p, @item);



    Author Comment

    Ahh - one man's english is another man's bad english. ;-)

    The generic error message it return is just that: API_ERR. It's the only constant with no details.

    Doesn't the out qualifier work just as well? I used that to get the engine value earlier with no problem. (I just tried changing both to pointers as suggested to no avail)

    I checked the "demo" code earlier, and I'm doing everything it is doing:

        INFO_ITEM fle;
        strcpy(fle.ItemData.InfoFile.Path, FileName);
        strcpy(fle.ItemData.InfoFile.Mode, "rb");

        api_OpenItem(Opt->clid, &fle, &item)

    The demo app seems to work ok, so I can't blame the dll - yet. =\
    LVL 26

    Accepted Solution


    Yes, the qualifiers should be the same, but some API's allow null to be passed (and therein would lie the difference). It was just a shot...

    Anyways, I checked all the structs, and they are the same size regardless of packed, so the problem does not appear to be there. The code you have appears to be the same as the demo..... as far as I can tell (though I don't see the defs for API_CLID or API_ITEM, so can't say for sure). And the file name you are passing is fully qualified as well?...

    Other than that, it really is impossible to say without more to go on. Which leads to the next question...

    Is this an open source library (something that someone else could check out)?



    Author Comment


    Ok, thanks for the help. I came here with the idea that the answer just might be that I'm doing everything right (at least as far as the structs, types, and conventions go). I guess my next step is to look into possible configuration issues. I also discovered a Debug mode call I'm going to try out.

    It's not open source, unfortunately, and I've even obscured a few of the names of the function calls due to my NDA. Such is life.

    Muchas gracias; answer accepted. :-)
    LVL 26

    Expert Comment

    by:Russell Libby
    Thanks, and sorry I could not help further with this...


    Featured Post

    IT, Stop Being Called Into Every Meeting

    Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

    Join & Write a Comment

    Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
    In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
    Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
    Here's a very brief overview of the methods PRTG Network Monitor ( offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

    734 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    18 Experts available now in Live!

    Get 1:1 Help Now