Delphi XE2:调用WinAPI EnumResourceNames会导致Win64平台中的访问冲突 [英] Delphi XE2: Invoke WinAPI EnumResourceNames cause access violation in Win64 platform
问题描述
在Delphi XE2 Win32平台上运行以下代码即可。但是,如果在调试模式下运行,则在win64平台上编译的同一代码将在 EnumRCDataProc中导致访问冲突:
Running the following code in Delphi XE2 Win32 platform works. However, the same code compile in win64 platform will cause access violation in "EnumRCDataProc" if run in debug mode:
procedure TForm2.Button1Click(Sender: TObject);
function EnumRCDataProc(hModule: THandle; lpszType, lpszName: PChar; lParam:
NativeInt): Boolean; stdcall;
begin
TStrings(lParam).Add(lpszName);
Result := True;
end;
var k: NativeInt;
L: TStringList;
H: THandle;
begin
H := LoadPackage('resource.bpl');
L := TStringList.Create;
try
EnumResourceNames(H, RT_RCDATA, @EnumRCDataProc, NativeInt(L));
ShowMessage(L.Text);
finally
L.Free;
UnloadPackage(H);
end;
end;
在Win64平台上的Delphi XE2 IDE中调试代码时,我发现EnumRCDataProc中hModule的值不与变量H不匹配。我怀疑我为EnumRCDataProc构造的参数可能有问题。但是,我不知道怎么做。有想法吗?
When debug the code in Delphi XE2 IDE on Win64 platform, I found the value of hModule in EnumRCDataProc doesn't match with variable H. I suspect that might be something wrong about the parameters I constructed for the EnumRCDataProc. However, I can't figure out how. Any ideas?
推荐答案
问题是您已经制作了 EnumRCDataProc
a当地程序。您需要将其移到方法之外。
The problem is that you have made EnumRCDataProc
a local procedure. You need to move it outside the method.
function EnumRCDataProc(hModule: HMODULE; lpszType, lpszName: PChar; lParam:
NativeInt): BOOL; stdcall;
begin
TStrings(lParam).Add(lpszName);
Result := True;
end;
procedure TForm2.Button1Click(Sender: TObject);
var k: NativeInt;
L: TStringList;
H: HMODULE;
begin
H := LoadPackage('resource.bpl');
L := TStringList.Create;
try
EnumResourceNames(H, RT_RCDATA, @EnumRCDataProc, NativeInt(L));
ShowMessage(L.Text);
finally
L.Free;
UnloadPackage(H);
end;
end;
在第一次检查时,我希望编译器会产生您的代码错误:
On first inspection I expected that the compiler would emit an error with your code:
E2094分配给过程变量的本地过程/函数回调
E2094 Local procedure/function 'Callback' assigned to procedure variable
但事实并非如此。我进行了更深入的挖掘,发现 EnumResourceNames
的回调参数声明为类型 Pointer
。如果标头转换已将其声明为类型化的回调参数,则确实会发出上述错误消息。在我看来,标题翻译在这方面很差。放弃类型系统的安全性似乎无济于事。
But it does not do so. I dug a little deeper and discovered that the callback parameter for EnumResourceNames
is declared as type Pointer
. If the header translation had declared this as a typed callback parameter then the above error message would indeed have been emitted. To my mind the header translation is poor in this regard. There seems very little to be gained from abandoning the safety of the type system.
您的代码在32位代码中工作的事实只是一个偶然的巧合,这取决于实现细节。您的运气用完了64位。同样,如果启用了类型检查系统,则编译器可能会立即告诉您出了什么问题。
The fact that your code works in 32 bit code is just a happy coincidence that relies on implementation details. Your luck runs out on 64 bit. Again, if the type checking system had been enabled, the compiler could have told you what was wrong immediately.
一些其他注释:
-
EnumRCDataProc
的声明中有几个错误的类型:hModule
的类型应为HMODULE
,函数结果应为BOOL
。 -
LoadPackage
是获得模块句柄的一种相当重量级的方法。我希望看到LoadLibraryEx
和LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE
和LOAD_LIBRARY_AS_IMAGE_RESOURCE
选项。 / li>
- The
EnumRCDataProc
has a couple of incorrect types in its declaration:hModule
should be of typeHMODULE
and the function result should beBOOL
. LoadPackage
is a rather heavyweight approach to getting a module handle. I would prefer to seeLoadLibraryEx
with theLOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE
andLOAD_LIBRARY_AS_IMAGE_RESOURCE
options.
这篇关于Delphi XE2:调用WinAPI EnumResourceNames会导致Win64平台中的访问冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!