首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Delphi:从外部DLL (C++)调用函数后的访问冲突

Delphi:从外部DLL (C++)调用函数后的访问冲突
EN

Stack Overflow用户
提问于 2009-10-19 07:46:02
回答 4查看 5.5K关注 0票数 2

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

Scraper.cpp:

代码语言:javascript
复制
SCRAPER_API bool ScraperGetWinList(SWin winList[100])
{
    iCurrWin=0;
    memset(winList,0,100 * sizeof(SWin));
    return EnumWindows(EnumProcTopLevelWindowList, (LPARAM) winList);
}

Scrper.h:

代码语言:javascript
复制
#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应用程序中声明函数的方式

代码语言:javascript
复制
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:写地址0xffffc 0‘。进程停止了。使用步骤或运行继续。

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-10-19 07:47:59

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

代码语言:javascript
复制
extern "C"
{
    __declspec(dllexport)
    bool __stdcall ScraperGetWinList(SWin winList[100]);
}

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

代码语言:javascript
复制
EXPORTS
ScraperGetWinList

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

代码语言:javascript
复制
cl.exe foo.cpp foo.def

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

票数 3
EN

Stack Overflow用户

发布于 2009-10-19 22:01:45

如果使用打包的array1 1..512字符,则不需要ConvertToString()函数。

“打包的char数组”是与Delphi字符串兼容的赋值(这可以追溯到Pascal填充的char数组的早期形式,char是字符串类型)。您可能需要对null ($0)字符的结果进行批注,以找到C-字符串的结尾。

另外,您使用的是什么Delphi版本?如果德尔菲2009 +你将需要使用包装阵列1.512的AnsiChar

票数 0
EN

Stack Overflow用户

发布于 2009-10-20 03:57:57

如果知道您的访问冲突具体发生在哪里,那就太好了。您的运行时试图访问的变量/内存位置是什么?

然后找出这个位置是否应该是可访问的,如果是的话,为什么不能。

我怀疑:您访问一个未正确初始化的数组元素。

代码语言:javascript
复制
  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;

任一

  • dll没有正确地初始化它,
  • 或者有另一种方法可以找出最后一个元素。
  • 或者您只是简单地运行了数组:101元素也被取消引用。和102,如果该内存位置碰巧包含0字符.
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1587410

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档