有一个用C++编写并编译成DLL的函数,我想在我的Delphi应用程序中使用它。
Scraper.cpp:
SCRAPER_API bool ScraperGetWinList(SWin winList[100])
{
iCurrWin=0;
memset(winList,0,100 * sizeof(SWin));
return EnumWindows(EnumProcTopLevelWindowList, (LPARAM) winList);
}Scrper.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:写地址0xffffc 0‘。进程停止了。使用步骤或运行继续。
如果我在__stdcall和Scraper.h中添加了SCRAPER_API bool(在SCRAPER_API bool之后),那么Delphi应用程序根本就不会启动:过程入口点ScraperGetWinList无法位于动态链接库Scraper.dll中。
发布于 2009-10-19 07:47:59
你需要把__stdcall放在bool之后。在所有宏展开之后,完整的声明应该如下所示:
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使用stdcall,方法是在Delphi函数声明中的stdcall之前插入external关键字。
发布于 2009-10-19 22:01:45
如果使用打包的array1 1..512字符,则不需要ConvertToString()函数。
“打包的char数组”是与Delphi字符串兼容的赋值(这可以追溯到Pascal填充的char数组的早期形式,char是字符串类型)。您可能需要对null ($0)字符的结果进行批注,以找到C-字符串的结尾。
另外,您使用的是什么Delphi版本?如果德尔菲2009 +你将需要使用包装阵列1.512的AnsiChar;
发布于 2009-10-20 03:57:57
如果知道您的访问冲突具体发生在哪里,那就太好了。您的运行时试图访问的变量/内存位置是什么?
然后找出这个位置是否应该是可访问的,如果是的话,为什么不能。
我怀疑:您访问一个未正确初始化的数组元素。
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;任一
https://stackoverflow.com/questions/1587410
复制相似问题