RTTI
2022. 7. 15. 16:52
삽질/COM
C++ 자체도 일단은, RTTI를 지원한다. 하지만, 성능상의 이유로, Unreal이나, Unity는 내부에 자체적으로 RTTI가 구현이 되어있다. 내가 작성한 버전은, template과 static의 특성을 사용한다. static 변수는 한 번만 초기화되는 녀석이므로, 매크로를 이용하여, Type을 string으로 변환하여, static 메모리에 저장한다. 이후 RTTI가 요구되는 클래스에 매크로를 추가해 주고, RTTI가 필요할 때, template type deduction에 의해 RTTI가 가능해진다. class RTTI { public: virtual const size_t TypeIdInstance() const = 0; virtual RTTI* QueryInterface(const size_..
Trace
2020. 11. 13. 10:47
삽질/COM
1. Trace는 단순한 추적 기능을 구현하는 것을 말한다. 2. printf는 출력을 디버거로 보내지 않기 때문에 부적절하다. 3. OutputDebugString 함수는 커널을 통해서 디버거에 문자열을 전달할 수 있지만, 릴리즈 버전에서는 노출되지 않는다. 4. Event Tracing은 릴리즈 버전에서도 제어 및 활성화할 수 있는 강력한 기능을 제공하지만, 간단한 추적을 하기에는 적합하지 않다. #pragma once #include #include #include #define ASSERT _ASSERTE #ifdef _DEBUG #define VERIFY ASSERT #else #define VERIFY(expression) (expression) #endif #ifdef _DEBUG inlin..

Verify
2020. 11. 13. 06:33
삽질/COM
1. Windows API 같은 API의 일부 메소드는 불리언 값을 반환하는 Verify 매크로를 통해서, 오류 상황을 가정하여 작성되었기 때문에, Assert 만큼 엄격하지는 않다. 2. 릴리즈 버전에서 완전히 없애기 곤란한 경우, Verify 매크로를 사용하기 때문에 보조 디버그 도구로 필수적이다. 3. Handle 객체는 복사가 일어나지 않기 때문에, 아래 코드는 오류를 발생하는 코드이다. e와 e2는 같은 값을 가지기 때문에, e의 소멸자가 호출되면, e2는 존재하지 않는 주소를 가리키게 되어, e2의 소멸자는 예외를 발생시킨다. #include #include #define ASSERT _ASSERTE #ifdef _DEBUG #define VERIFY ASSERT #else #define VE..
COM study note 8 IUnknown C# 버전
2020. 10. 30. 12:12
삽질/COM
1. COM은 바이너리 스탠다드이다. 그러나 CLR은 좀더 상위 레벨에서 COM을 보조하는 역활을 한다. 2. 그럼에도 CLR은 완벽하지 않아서, 직접 C++과 C#의 갭을 메우는 짓이 필요하다. using System.Runtime.InteropServices; [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("26e278ff-5641-46da-94b3-1da3f19b315a")] interface IHen { [PreserveSig] void Cluck(); [PreserveSig] void Roost(); } [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("06845df9-7bb9..
COM study note 8 IUnknown 이식
2020. 10. 30. 00:06
삽질/COM
GUID는 COM 인터페이스를 위한 식별자이다. 128bit Globally unique identifier UUID IID CLSID 도 결국엔 GUID 임 1 Library 헤더에 이식하기 위해서, PowerShell 에서 uuid를 생성한다음 클립보드에 복사한다. uuidgen | clip 2. uuid로 인터페이스 구조체를 수정한다. //Library.h #pragma once #include struct __declspec(uuid("26e278ff-5641-46da-94b3-1da3f19b315a")) IHen : IUnknown { virtual void __stdcall Cluck() = 0; virtual void __stdcall Roost() = 0; }; struct __declsp..
COM study note 7
2020. 10. 29. 17:01
삽질/COM
1. HRESULT는 그냥 long 혹은 signed long int 이다. (32bit) Severity code(1bit) : Success or Fail Facility code(11bit) : application 에러보다는 Infrastructure 에러와 연관된 부분 Status code(16bit) : 실질적인 에러 코드 //관련 매크로 #define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) #define FAILED(hr) ((HRESULT)(hr) < 0) //매크로 안쓴는 버전 if(S_OK == hr) ... if(S_OK !+ hr) ... struct ComException { HRESULT error; ComException(const HRESULT hr) ..

COM study note 6 인터페이스 상속
2020. 10. 28. 17:47
삽질/COM
1. 다이아몬드 상속을 받는 경우, 문제를 야기할 수 있지만, 명시적으로 캐스팅을 함으로써 문제를 해결한다. //Library.h #pragma once struct IObject { virtual void __stdcall Addref() = 0; virtual void __stdcall Release() = 0; virtual void* __stdcall As(const char* type) = 0; }; struct IHen : IObject { virtual void __stdcall Cluck() = 0; virtual void __stdcall Roost() = 0; }; struct IHen2 : IHen { virtual void __stdcall Forage() = 0; }; struct..
COM study note 5 레퍼런스 카운터
2020. 10. 28. 13:18
삽질/COM
1. 이런 저런 오류를 피하기 위해서, COM 객체를 레퍼런스 카운터를 통해서 수명 관리하는 것이 국룰이다. 2. 인터페이스를 만들고 구현은 파생에서 하도록 한다. //Library.h #pragma once struct IHen { virtual void __stdcall Cluck() = 0; virtual void __stdcall Roost() = 0; virtual void __stdcall Addref() = 0; virtual void __stdcall Release() = 0; }; IHen* __stdcall CreateHen(); 3. 멤버 변수로 레퍼런스 카운터를 추가하고, 초기화는 유니폼으로 하는 것이 국룰이다. Release에서는 레퍼런스 카운터가 0이 되면 인스턴스를 자동으로 삭..