c++ - Delphi:从外部 DLL (C++) 调用函数后发生访问冲突

标签 c++ delphi dll dllimport access-violation

有一个函数,用 C++ 编写并编译为 DLL,我想在我的 Delphi 应用程序中使用它。

刮刀.cpp:

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

刮刀.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]);
}

这是我在 Delphi 应用程序 中声明函数的方式:

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';

函数有效,但完成后,我收到调试器故障通知:项目...故障消息:“0x0012f773 处的访问冲突:地址 0xffffffc0 的写入”。进程停止。使用 Step 或 Run 继续。

如果我在 Scraper.cpp 和 Scraper.h 中添加 __stdcall(在 SCRAPER_API bool 之后),那么 Delphi 应用程序根本不会启动:过程入口点 ScraperGetWinList 无法位于动态链接库 Scraper.dll 中。

最佳答案

您需要在bool 之后放置__stdcall。在所有宏展开之后,完整的声明应该如下所示:

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

编辑:看起来您还需要一个 .def 文件。它是一个文件,列出了 DLL 中导出的每个函数,在这种情况下,只需要强制 C++ 编译器不破坏导出的名称。内容是这样的:

EXPORTS
ScraperGetWinList

我不确定您使用的是哪个 C++ 编译器,但通常您只需指定 .def 文件和 .cpp;例如,以下适用于 VC++:

cl.exe foo.cpp foo.def

此外,您还需要通过在 Delphi 函数声明中的 external 之前插入 stdcall 关键字来告诉 Delphi 使用 stdcall。

关于c++ - Delphi:从外部 DLL (C++) 调用函数后发生访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1587410/

相关文章:

android - delphi xe6 目标多字节代码页中不存在 Unicode 字符的映射

C++ DLL 不加载调试符号

c++ - 可能的类/析构函数设置问题,收到错误消息 'unresolved external symbol'

c++ - 如何在obj文件中使用面值(opengl c++)

C++ 我怎样才能改进这个模板元程序来返回包含大小的数组?

c++ - 控制台上的陷阱退出

c++ - SDL_RenderReadPixels 返回一个黑色矩形?

windows - 为什么 TClientSocket.OnRead 事件会为单个服务器发送两次

sockets - 通过TClientSocket从网站加载图像

windows - Windows 上的胖二进制文件?