2012-01-12 1 views
5

Delphi XE2 Win32 플랫폼에서 다음 코드를 실행하면 작동합니다.Delphi XE2 : WinAPI 호출 EnumResourceNames가 Win64 플랫폼에서 액세스 위반을 야기 함

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 플랫폼에서 델파이 XE2 IDE에서 코드를 디버깅, 내가 EnumRCDataProc에 HMODULE의 가치를 발견 : 디버그 모드에서 실행되는 경우, 동일한 코드는 "EnumRCDataProc"에서 액세스 위반이 발생할 것이다하는 Win64 플랫폼에서 컴파일 변수 H와 일치하지 않습니다. EnumRCDataProc에 대해 생성 한 매개 변수에 문제가있을 수 있습니다. 그러나, 나는 방법을 이해할 수 없다. 어떤 아이디어?

답변

5

문제는 EnumRCDataProc을 로컬 절차로 변경 한 것입니다. 메소드 밖으로 이동해야합니다.

E2094 로컬 절차/기능 '콜백'은 프로 시저 변수에 할당

는하지만 수행합니다

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; 

먼저 검사에 나는 컴파일러가 코드 오류를 방출 할 것으로 예상 그러지 마라. 좀 더 깊이 파고 EnumResourceNames의 콜백 매개 변수가 Pointer 유형으로 선언되었습니다. 헤더 변환이 형식화 된 콜백 매개 변수로 선언 된 경우 실제로 위의 오류 메시지가 표시됩니다. 내 머리 속에서 헤더 번역은이 점에서 열악하다. 형식 시스템의 안전을 포기함으로써 얻을 수있는 것은 거의없는 것 같습니다.

코드가 32 비트 코드에서 작동한다는 사실은 구현 세부 사항에 의존하는 행복한 우연의 일치입니다. 행운은 64 비트에서 다 떨어졌습니다. 다시 말하지만, 타입 검사 시스템이 활성화 되었다면, 컴파일러는 무엇이 잘못 되었습니까?

일부 다른 의견 :

  1. EnumRCDataProc는 선언에 잘못된 유형의 몇 가지가 있습니다 hModule 유형 HMODULE이어야하고 함수의 결과는 BOOL을해야합니다.
  2. LoadPackage은 모듈 핸들을 얻는 데 다소 힘든 방법입니다. LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVELOAD_LIBRARY_AS_IMAGE_RESOURCE 옵션을 사용하는 LoadLibraryEx을 선호합니다.
+0

컴파일러가 그것에 대해 불평해서는 안됩니다. 로컬 enum 함수는 전혀 문제가되지 않습니다. – OnTheFly

+0

추측 컨데, 왜 그걸 내야합니까? p – OnTheFly

+1

콜백이 문제가되어서는 안되는 양식을 액세스하지 않는 한. 그런 다음 다시 그 목적을 위해서만 콜백을 꺼내는 것이 올바른 일입니다. 파업은 무엇을 의미합니까? 그것은 위의 대답의 일부를 무효화합니까? –