Delphi: Access violation after calling a function from an external DLL (C ++)

There is a function there, written in C ++ and compiled as a DLL, that I want to use in my Delphi application.

Scraper.cpp:

SCRAPER_API bool ScraperGetWinList(SWin winList[100])
{
    iCurrWin=0;
    memset(winList,0,100 * sizeof(SWin));
    return EnumWindows(EnumProcTopLevelWindowList, (LPARAM) winList);
}

      

Scraper.h:

#ifdef SCRAPER_EXPORTS
#define SCRAPER_API __declspec(dllexport)
#else
#define SCRAPER_API __declspec(dllimport)
#endif

struct SWin
{
    char title[512];
    HWND hwnd;
};

extern "C" {
    SCRAPER_API bool ScraperGetWinList(SWin winList[100]);
}

      

This is how I declare a function in a Delphi application :

type
  tWin = record
    Title: Array [0..511] of Char;
    hWnd: HWND;
  end;

  tWinList = Array [0..99] of tWin;

function ScraperGetWinList(var WinList: tWinList): Boolean; stdcall; external 'Scraper.dll';

      

The function works, but when finished, I get a debugger error: Project ... with an error with the message: "Access violation at 0x0012f773: writing address 0xffffffc0". The process has been stopped. Use Step or Run to continue.

If I add __stdcall

(after SCRAPER_API bool

) to Scraper.cpp and Scraper.h, then the Delphi application does not start at all: the entry point to the ScraperGetWinList procedure cannot be located in the Scraper .dll dynamic link library.

+2


source to share


4 answers


You need to put __stdcall

after bool

. The complete declaration, after expanding the macros, should look like this:

extern "C"
{
    __declspec(dllexport)
    bool __stdcall ScraperGetWinList(SWin winList[100]);
}

      

EDIT: Looks like you also need a .def file. This is the file that lists all the functions exported to the DLL, in which case it only needed to force the C ++ compiler not to interfere with the exported names. The content will be as follows:

EXPORTS
ScraperGetWinList

      



I'm not sure which C ++ compiler you are using, but usually you just specify the .def file along with the .cpp; for example the following works for VC ++:

cl.exe foo.cpp foo.def

      

In addition, you will need to tell Delphi to use stdcall by adding the keyword stdcall

just before external

the Delphi function declaration.

+3


source


If you are using a packed array [1..512] of char, you do not need the ConvertToString () function.

"packed char array" is a Delphi string compatible assignment (this refers to the very early forms of pascal array from char WAS string type). You will need a scrab result for a null ($ 0) char to find the end of the C string



Also which version of Delphi are you using? if Delphi 2009+ you need to use packed array [1..512] from AnsiChar ;

0


source


It would be good to know exactly where your access violation is happening. What variable / memory location is your work environment trying to access?

Then find out if the location should really be available, and if so, why it isn't.

My suspicion: you are accessing an array element that is not initialized correctly.

  Index := 0;
  S := ConvertToString(myWinList[Index].Title); 
  while S <> '' do
  begin
    WinListMemo.Lines.Add(S);
    Inc(Index);
    //////// Is Index pointing to a valid entry here?  No check!
    S := ConvertToString(myWinList[Index].Title);
  end;

      

Or

  • dll does not initialize it correctly,
  • or is there another way to find out the last item.
  • or you just deleted the array completely: element 101 is dereferenced as well. and 102nd if this memory location contains character 0.
0


source


Make sure your Delphi function definition matches what you also declare a C ++ function. In particular, make sure you have a stdcall at the end and that your bool values ​​are consistent. C ++ and Delphi use different values ​​and sizes for bool, depending on the C ++ compiler, so it's better to use an appropriate Integer size. Since the bool size may not match the C ++ size, it can affect the stack and therefore cause access violations.

[edited to remove mixed language mixing reaction]

-1


source







All Articles