64비트 애플리케이션 개발에 따른 델파이 변경사항을 알아봅니다.

 

* 아래 제목을 클릭해 원하는 내용으로 바로 이동할 수 있습니다.

 

64비트 개발 준비하기

  - 64비트 애플리케이션 개발환경

  - 32비트와 64비트 별도의 실행파일 필요

64비트 컴포넌트와 라이브러리

  - 64비트 컴포넌트 - 써드파티

  - 64비트 컴포넌트 - 자체제작

64비트 지원에 따른 델파이 변경사항

  - 32비트와 64비트 데이터 타입의 변경

  - 64비트 어셈블리 프로그래밍

  - Windows api 사용 시 주의사항

 

그 외의 문제 추가검토하기

 

64비트 개발 준비하기

개발 PC가 64비트 시스템이라면 32비트와 동일한 환경에서 개발할 수 있습니다.

만약, 개발 PC가 32비트 시스템이라면, 64비트 시스템이 설치된 원격 데스크탑의 PAServer(Platform Assistant Server: 원격 디버거와 흡사)를 이용해 개발할 수 있습니다. 32비트 PC에서 64비트 PC에 연결하기 위한 구성방법은 Connecting_Your_32-bit_PC_to_a_Win64_PC에서 확인할 수 있습니다.

 

32비트와 64비트 애플리케이션을 제공하기 위해서는, 두개의 실행파일을 제공해야 합니다.

 

64비트 실행파일을 생성하기 위해서는, 프로젝트 매니저에서 64-bit Windows 타겟 플랫폼을 추가(이미 추가한 경우 활성화)하고 빌드할 수 있습니다.

001.png

 

64비트 컴포넌트와 라이브러리

64비트 애플리케이션에서 사용하고자 하는 써드파티 컴포넌트는 64비트 빌드를 지원해야 합니다.

컴포넌트 제작사 홈페이지의 설명을 참고하거나, 설명이 되어 있지 않은 컴포넌트의 경우 직접 64비트 프로젝트 생성 후 테스트 과정을 진행해야 합니다.

만약, 64비트를 지원하지 않는다면 다른 컴포넌트로 대체하거나, 소스코드가 있다면 직접 64비트를 지원하도록 마이그레이션 해야 합니다.

64비트 지원하도록 마이그레이션 하는 절차는 64비트 컴포넌트 - 자체제작 항목과 64비트 지원에 따른 델파이 변경사항을 참고하기 바랍니다.

 

64비트 컴포넌트 - 자체제작

64비트 컴포넌트를 제작하는 경우 32비트와 64비트를 모두 지원해야 합니다. 델파이 IDE는 32비트 애플리케이션 입니다. IDE에서 컴포넌트를 사용하기 위해 32비트 컴포넌트 패키지가 필요합니다.

 

자체 제작한 32비트 컴포넌트라면 64비트 지원하도록 타겟 플랫폼에 64-bit Windows를 추가하고, 64비트 지원에 따른 델파이 변경사항 항목을 참고해 코드를 마이그레이션 해야 합니다.

 

64비트 플랫폼에서 Tool Palette에 컴포넌트를 활성화 하기

컴포넌트가 32비트와 64비트 모두 지원하기 위해, 아래 코드를 참고해 등록되는 컴포넌트의 클래스 위에 ComponentPlatformAttribute 속성을 추가합니다.

  [ComponentPlatformsAttribute(pidWin32 or pidWin64)]

  TTeThemeEngine = class(TComponent)

  private

    FDeltaHue: integer;

    FDeltaBrightness: integer;

 

등록되는 컴포넌트의 클래스 종류는 디자인 타임 패키지의 "RegisterComponent" 메소드 호출하는 부분을 참고하기 바랍니다.

procedure Register;

begin

  RegisterComponents('ThemeEngine', [TTeThemeEngine, TTeThemeList, TTeThemeLink,

    TTeManager, TTeAdapter, TTeThemeSwitcher, TTeThemePreview,

    TTeForm, TTeForm2, TTeMDIChild, TTeMenuBar, TTePopupMenu]);

 

컴포넌트 설치 단계

컴포넌트 설치는 32비트 컴포넌트 패키지에서만 진행합니다. 다음 순서대로 설치하는 것이 좋습니다.

1, 64비트 플랫폼에서 컴포넌트 빌드

2, 32비트 플랫폼에서 컴포넌트 빌드

3, 32비트 플랫폼에서 컴포넌트 설치

32비트와 64비트 데이터 타입의 변경

정수형 데이터 타입

부호있는 정수

부호없는 정수

Delphi / 32

Delphi / 64

ShortInt

Byte

1 바이트

SmallInt

Word

2 바이트

LongInt

LongWord

4 바이트

FixedInt

FixedUInt

4 바이트

Integer

Cardinal

4 바이트

Int64

UInt64

8 바이트

NativeInt

NativeUInt

4 바이트

8 바이트

대부분의 정수형 데이터 크기는 64비트에서 32비트의 데이터 크기를 유지합니다.

 

포인터 타입

포인터 형

Delphi / 32

Delphi / 64

Pointer

 4 바이트

 8 바이트

THandle

string

클래스 인스턴스

클래스 참조

인터페이스

AnsiString

WideString

UnicodeString

process pointer

dynamic array

PAnsiChar

PWideChar

PChar

64비트 포인터 크기는 32비트와 다릅니다. 포인터 크기가 Integer 또는 LongInt와 같다는 가정의 코드와 포인터 크기가 4라는 가정의 코드를 검토해야 합니다.

 

포인터 증가 코드의 주의

 // 올바른

 MyPtr := PByte(P) + 10;

 

 // 하위 호환성 유지

 MyPtr := PAnsiChar(P) + 10;

 

 // 잘못된

 MyPtr := Pointer(Integer(p) + 10);

 

포인터 크기를 4로 가정할 수 없습니다.

 // 올바른

 Move(FSelection[Index + 1], FSelection(Index), (FselectionCount – Index – 1) * Sizeof(Pointer));

 

 // 잘못된 

 Move(FSelection[Index + 1], FSelection(Index), (FselectionCount – Index – 1) * 4);

 

64비트 어셈블리 프로그래밍

64비트 어셈블리 코드를 지원합니다. 하지만 몇가지 제한이 있습니다. 루틴(함수 구현부)의 전부를 어셈블리 언어로 작성해야 합니다.(어셈블리 언어와 델파이 언어를 혼용할 수 없습니다.)

64비트 윈도우 CPU의 레지스터는 32비트 윈도우 CPU 레지스터의 2배의 폭이 있습니다.

32비트와 64비트 어셈블리 코드를 분기할 경우 아래 조건부 컴파일 구문을 사용할 수 있습니다.

 {$IFDEF CPUX86} 

  asm 

    // 32 비트 어셈블리 구현

  end ; 

  {$ENDIF CPUX86} 

  {$IFDEF CPUX64} 

  asm 

    // 64 비트 어셈블리 구현

  end ; 

 {$ENDIF CPUX64}

 

Windows api 사용 시 주의사항

 

WPARAM / LPARAM 사용 시 주의 사항

SendMessage / PostMessage / TControl.Perform에 전달할 wParam, lParam 파라메터는 Integer / LongInt 값이 아닌 WPARAM / LPARAM으로 형변환 해야 합니다.

// 올바른

SendMessage(hWnd, WM_SETTEXT, 0, LPARAM(@MyCharArray));

 

// 잘못된 

SendMessage(hWnd, WM_SETTEXT, 0, Integer(@MyCharArray));

 

SetWindowLong / GetWindowLong의 포인터와 핸들 반환 시 주의사항 

SetwindowLong / GetWindowLong의 포인터와 핸들을 반환할 때 GWLP_HINSTANCE, GWLP_ID, GWLP_USERDATA, GWLP_HWNDPARENT 및 GWLP_WNDPROC에 대해 SetWindowLongPtr / GetwindowLongPtr로 변경해야 합니다. SetWindowLongPtr에 전달 된 포인터는 Integer / LongInt가 아닌 LONG_PTR 형식을 지정해야 합니다.

// 올바른

SetWindowLongPtr(hWnd, GWLP_WNDPROC, LONG_PTR(@MyWIndowProc));

 

// 잘못된

SetWindowLong(hWnd, GWLP_WNDPROC, LongInt(@MyWindowProc));

 

TMessage.Result에 포인터 할당 시 주의사항

TMessage.Result 필드에 할당된 포인터는 Integer / LongInt 대신 LRESULT로 형변환 해야 합니다.

// 올바른

Message.Result := LRESULT(Self);

 

// 잘못된

Message.Result := Integer(Self);

 

마이그레이션 중 위에서 설명한 내용 외의 문제가 발생한다면 다음 문서에서 "이슈"와 "이슈에 대한 조치사항"을 찾아보시기 바랍니다.

 - [바로가기] 데브기어-마이그레이션-이슈공유 문서 보기

 

위 문서에도 원하는 답이 없다면 개발자 Q&A에서 검색 후, 결과가 없다면 질문을 등록해 다른 개발자들의 도움을 받아보시기 바랍니다.

 - [바로가기] 데브기어 개발자 Q&A