-
[DirectX] 스마트 포인터 ComPtrC++/미분류 2024. 3. 21. 16:20
스마트 포인터는 포인터를 래핑하여, 자원의 누수를 최소화 하는 것에 목적을 둔 객체입니다.
C++에서 기본적으로 제공하는 스마트 포인터에 관한 글은 아래의 다른 글을 참조해주세요.
[Effective Modern C++] Smart pointer : std::unique_ptr<>
[Effective Modern C++] Smart pointer : std::shared_ptr<>
[Effective Modern C++] Smart pointer : std::weak_ptr<>
[Effective Modern C++] Smart pointer : std::make_unique<>, std::make_shared<>DirectX의 COM객체들은 위 스마트 포인터가 아닌, COM 인터페이스를 위한 스마트 포인터를 사용할 수 있습니다.
Windows API의 발전에 따라 COM 스마트 포인터도 여러 형태로 발전해왔습니다.
이번 글에서는 그 중 WTL(Windows Template Library)에서 사용되는 ComPtr을 사용해보겠습니다.
이번 글은 지난 글(비트맵 움직이기)에서 코드가 이어지며, 지난 글의 예제에서 사용된 객체를 ComPtr로 바꾸어 보겠습니다.
1. ComPtr의 선언
더보기ComPtr은 다음과 같은 선언 후 사용할 수 있습니다.
#include <wrl/client.h>
ComPtr클래스는 다음과 같이 네임스페이스와 함께 사용할 수 있습니다.
Microsoft::WRL::ComPtr<t>
다음과 같이 using 구문으로 네임스페이스를 생략할 수 있습니다.
using namespace Microsoft::WRL;
2. ComPtr의 사용
더보기ComPtr은 DirectX의 COM 인터페이스 객체에 사용할 수 있습니다.
기본적으로는 일반 포인터와 동일하게 취급할 수 있으며, 객체에 직접 접근하려 할 경우 다음과 같이 사용할 수 있습니다.
ComPtr<ID2D1Factory> foo; foo.Get();
ComPtr객체의 Get함수는 래핑된 포인터를 반환합니다.
이제 ComPtr을 기존 코드에 적용해보겠습니다.
다음은 ID2D1Factory객체의 기존 선언과, 초기화 코드입니다.
class MyApp { private: ID2D1Factory* myDirect2dFactory = nullptr; ... }; HRESULT MyApp::CreateDeviceIndependentResources() { ... hr = D2D1CreateFactory( D2D1_FACTORY_TYPE_MULTI_THREADED, &myDirect2dFactory ); ... }
위 코드는 아래와 같이 ComPtr로 래핑할 수 있습니다.
class MyApp { private: ComPtr<ID2D1Factory> myDirect2dFactory; ... }; HRESULT MyApp::CreateDeviceIndependentResources() { ... hr = D2D1CreateFactory( D2D1_FACTORY_TYPE_MULTI_THREADED, IID_PPV_ARGS(&myDirect2dFactory) ); ... }
Factory를 초기화하는 D2D1CreateFactory함수는 여러 오버로딩이 있습니다.
그 중 객체의 IID와 객체의 void**를 매개변수로 받는 오버로딩을 사용했습니다.
IID_PPV_ARGS매크로는 아래와 같이 정의되어있습니다.
#define IID_PPV_ARGS(ppType) __uuidof(**(ppType)), IID_PPV_ARGS_Helper(ppType)
지정한 타입에 해당하는 IID와 포인터로 변환해주는 코드입니다.
또한, 소멸자 등에 사용된 SAFE_RELEASE를 제거했습니다.
ComPtr을 통해 선언한 객체는 스마트 포인터와 같이 동작하여, 참조 횟수가 0이 될 경우 자동으로 소멸됩니다.
MyApp::~MyApp() { DiscardDeviceResources(); //SAFE_RELEASE(myDirect2dFactory); }
본문에서는 ID2D1Factory객체에 대해서 ComPtr로 래핑했지만, DirectX에서 제공하는 COM인터페이스는 모두 ComPtr로 래핑이 가능합니다.
본 프로젝트에서는 I~~로 시작하는 객체가 이에 해당합니다.
또한, 내용을 진행하며 만든 MyBitmap객체는 COM객체가 아니기 때문에, C++의 스마트 포인터로 바꾸었습니다.
이번 글에 적용된 전체 코드는 아래 Github에서 확인하실 수 있습니다.
이번 글이 도움이 되셨기를 바랍니다.
감사합니다.
'C++ > 미분류' 카테고리의 다른 글
[Direct2D] ID2D1Effect 사용하기 (0) 2024.04.05 [Direct2D] Device context 사용하기 (ID2D1DeviceContext) (1) 2024.03.29 [Direct2D] 비트맵 이미지 움직이기 (2) (0) 2024.03.13 [Direct2D] 비트맵 이미지 움직이기 (1) (0) 2024.03.10 [Direct2D] 움직이는 비트맵 이미지 그리기 (1) 2024.02.28