0

我已经在 Stackoverflow 上搜索了我遇到的问题,但它们都非常针对特定的访问冲突。

我认为我遇到问题的一段代码是一个名为 的函数MpqExtractFile,它存储在一个 DLL 中。

功能:

function MpqExtractFile(var hMPQ: Integer; szToExtract, szExtracted: AnsiString): Boolean; stdcall; external 'MpqLib.dll' name 'B2';

称呼:

if MpqExtractFile(hMPQ, 'war3map.j', AnsiString(tempDir+'\war3map.j')) = True
then ShowMessage('Success.')
else ShowMessage('Failed.');

执行此代码后,我的应用程序会引发访问冲突错误,因此ShowMessage根本不会显示。

我不确定以上是否足以估计问题可能是什么,但如果还有什么我应该告诉我的。

编辑

这是我一直在解释的 VB.NET 源代码的摘录:

Declare Function MpqExtractFile Lib "MpqLib.dll" Alias "B2" (ByVal hMPQ As Integer, ByVal szToExtract As String, ByVal szExtracted As String) As Boolean

我显然不熟悉其他语言的声明,但我在声明 VB 函数的同一个 VB 文件中找到了以下函数。

BOOL WINAPI MpqExtractFile(HANDLE hMpq, const char * szToExtract, const char * szExtracted);

提前谢谢你!

4

2 回答 2

7

AnsiString是完全错误的类型,除非 DLL 是在 Delphi/C++Builder 中编写并实际用于AnsiString其参数中。如果是这种情况,您需要知道 DLL 是用哪个版本的 Delphi/C++Builder 编写的,因为AnsiString2009 年更改了内存布局。

无论如何,跨 DLL 边界传递非 POD 数据是非常危险的,因此大多数 DLL 不会这样做。有问题的参数很可能是PAnsiChar相反的,例如:

function MpqExtractFile(var hMPQ: Integer; szToExtract, szExtracted: PAnsiChar): Boolean; stdcall; external 'MpqLib.dll' name 'B2'; 

.

if MpqExtractFile(hMPQ, 'war3map.j', PAnsiChar(AnsiString(tempDir+'\war3map.j'))) then
  ShowMessage('Success.') 
else
  ShowMessage('Failed.'); 

其他需要考虑的点:

1) 并非所有 DLL 都使用stdcall调用约定。像许多开源库一样,用 C 编写的 DLL 使用cdecl调用约定来代替并不罕见:

function MpqExtractFile(var hMPQ: Integer; szToExtract, szExtracted: PAnsiChar): Boolean; cdecl; external 'MpqLib.dll' name 'B2'; 

2) C 没有Boolean像 Delphi 和 C++ 那样的真正数据类型。C 代码使用Byte甚至Integer模仿Boolean.

为了在 Delphi 中使用 DLL,您确实需要知道其导出函数的实际正确声明。这在 C/C++ 中不是什么问题,因为大多数 DLL 都有一个提供声明的随附 .h 文件。你有这样的.h 文件吗?如果是这样,请在此处发布,以便有人可以验证您对 Delphi 的翻译。

更新:

根据新信息,正确的 Delphi 声明是这样的:

function MpqExtractFile(hMpq: THandle; const szToExtract, szExtracted: PAnsiChar): BOOL; stdcall; external 'MpqLib.dll' name 'B2';
于 2012-10-21T07:38:00.933 回答
4

您的 VB.net 声明是:

Declare Function MpqExtractFile Lib "MpqLib.dll" Alias "B2" (
    ByVal hMPQ As Integer, ByVal szToExtract As String, 
    ByVal szExtracted As String) As Boolean

等效的 Delphi 导入将是:

function MpqExtractFile(MpqExtractFile: Integer; 
    szToExtract, szExtracted: PAnsiChar): BOOL; 
    stdcall; external 'MpqLib.dll' name 'B2';

Delphi 字符串类型不应该用于互操作。p/invoke marshaller 将 String 映射到 C++ char*,它是 Delphi 中的 PAnsiChar。

这种任务确实应该使用 C++ 头文件来执行。你说你没有那个。如果 DLL 是用 C++ 编写的,那么头文件肯定存在。追踪它并将其作为您的来源是值得的。

于 2012-10-21T21:10:55.317 回答