d3dx9 - 21.10.07

김주현·2021년 10월 7일
0

d3dx9 3D

목록 보기
2/30

기본적인 수정

  1. hinst 와 hwnd 수정

  2. 메시지 루프 수정(GetMessage 를 PeekMessage로)
    GetMessage는 메시지가 없을경우 메시지가 들어올때까지 기다리고
    PeekMessage는 메시지가 없으면 다른코드를 처리하기위해 넘어감 PM_REMOVE는 메시지를 읽은뒤 제거하라는 뜻

  3. MainApp 생성관련함수 만들어주고 Client.cpp에서 헤더추가(추가포함디렉토리 설정)

MainApp 클래스
1. update의 역할을하는 Tick함수와 Render함수 선언
2. 멤버변수는 멤버함수의 구현을 위해 필요한 데이터로 이해하는게 편하다.
3. Client에서 Mainapp을 다 사용한후 delete로 삭제하기보단 함수를 통해 삭제
4. 레퍼런스 카운트를 통해 나의 참조갯수를 저장하고 참조갯수가 0이되면 Delete해주는 방식. 이를 CBase의 구현하고 모든 클래스의 부모로 사용
5. Engine에 CBase를 구현하고 Client에서 상속(Client에다가 만들면 엔진이 클라이언트에 의존적이됨 != 엔진은 한 클라이언트에 의존적이면 안됨 여러 클라이언트에서 사용)

Engine 프로젝트

  1. Cbase구현을 위해 win32 DLL 빈 프로젝트로 생성
  2. 폴더정리를 위해 프로젝트 삭제후 default,public,private,bin 생성
  3. SuperClass 필터안에 Base 클래스 생성
  4. Reference에 Engine에서 만든 라이브러리를 옮겨줌
  5. Client는 엔진이아닌 레퍼런스에 접근
  6. 라이브러리파일이란 실제 함수의 구현부
  7. 같은 프로젝트에선 헤더를 include를 해줬음
  8. 라이브러리 프로젝트를 빌드하면 exe가 아닌 lib파일이 생성됨
  9. Client는 헤더만 참조하고 함수의 본체는 라이브러리에서 참조함

Reference 폴더는 헤더를 저장할 폴더와 라이브러리를 저장할 폴더 2개를 가짐

  1. CBase클래스의 기능을 다구현하고 레퍼런스 폴더의 inc폴더로 Base.h를 복붙

Engine - Cbase 클래스

  1. 모든 클래스의 부모 클래스다 abstract 키워드 추가
  2. 생성자와 가상디폴트소멸자 생성
  3. private멤버변수로 unsigned long m_dwRecnt =0 선언 (현재 객체의 참조 갯수를 저장한다.)
  4. 레퍼런스 카운트를 증감시키는 함수가 필요함
  5. 증가를 위한 AddRef, 감소를 위한 Release 를 선언 두 함수는 반환값으로 현재 레퍼런스 카운트를 반환
  6. 애드는 m_dwRefCnt를 1증가 시키고 반환
  7. 릴리스는 m_dwRefCnt를 1감소 시키고 반환 반환값이 unsigned이기때문에 음수가 되게하면 안됨
    0일 때 릴리스를 호출하면 delete this를 통해 자신을 지워버리고 0을 리턴
    아닐떄는 1감소를 해주고 감소하기 전의 값을 리턴

1일 때 릴리스가 호출되면 0이되고 1을반환 - 아직 지워지지않음
다음 릴리스 호출때 삭제하고 0을 반환

com객체의 리턴방식과 유사한 방식

delete this 를 통해 삭제하면 CBase의 소멸자가 호출되면 가상 소멸자가이기때문에 자식이 먼저 삭제된후 부모의 소멸자가 호출됨.

이 순서를 변경( 자식 -> 부모가 아닌 부모->자식) 하고싶다면 기존 소멸자로는 불가능(무조건 최하단 자식부터) 이렇게 하고싶다면 순수 가상 함수 virtual void Free() = 0;를 선언 (자식에서 무조건 선언해줘야함) 기존대로 하고싶다면

자식의 Free에서 __super::Free()를 호출

기존 소멸자는 자식소멸자호출후 자동으로 부모소멸자를 호출
free는 호출하지않으면 자식 소멸자만 호출

결론 : free함수를 이용하면 호출자 호출 순서를 컨트롤 가능

  1. 당장은 CBase에서 동적으로 지워줄것이 없기때문에 자식의 Free에서 부모의 free를 호출해줄 필요가 없음

  2. 응용프로그램이 아니기 떄문에 엔진에서 F7을 통해 빌드해줌

  3. 이 클래스는 바깥으로 보내기위한 클래스라는것 키워드 추가해줘야함
    class _declspec(dllexport) - 클래스마다 지정해줘야함
    이제 빌드하면 lib파일이 생성됨
    lib파일에는 함수의 구현부들이 담겨있음

이제 Client에서 사용할수있게 설정

  1. 엔진에 lib파일을 복사해서 레퍼런스에 lib폴더에 복붙

  2. 엔진에 base.h파일을 복사해서 레퍼런스에 inc폴더에 복붙

  3. 다음 Client에서 사용시 포함 해주면됨 경로의 간편화를 위해 추가포함디렉토리에 레퍼런스폴더안에 inc폴더를 추가

  4. Client에서 using namespace Client 추가

  5. 라이브러리파일추가해줘야함 프로젝트속성에서 링커->추가종속성->Engine.lib추가

  6. 링커의 추가 라이브러리 디렉터리에 레퍼런스에 라이브러리 폴더를 추가

  7. CBase를 dllexport에서 dllimport로 변경 client기준으로는 입력이기때문
    하지만 이렇게 변경하는것은 불편하기때문에 매크로를 잡아줄것

  8. 구현부가 라이브러파일에 담기지않음 실제 구현부에 해당하는 파일들을 dll에 담아줌
    9.엔진의 dll파일은 client.exe 클라이언트 실행파일에 붙어야함
    10.정적라이브러리의 장점 - 빠르다 실제코드가 통합이되었기때문
    단점 - exe 파일의 크기 점점 커짐
    정적라이브러리로 만든 모든 프로젝트는 실행파일에 라이브러리의 코드가 다들어가기때문에 다수의 프로그램을 수행할때 공통되는 메모리를 중복해서 올려버림 메모리를 매우 많이 잡아먹게된다.

자세한 설명
https://luyin.tistory.com/201

  1. dll은 코드 자체가아닌 코드의 주소가 담겨있음 용량이 작고 다수의 프로그램을 실행해도 공통되는 라이브러리 실행해도 메모리를 공용해서 사용함
    프로그램이 가벼워짐 대신 호출속도는 정적보다는 좀 떨어짐

  2. 클라이언트에서 엔진프로젝트의 클래스 상속가능

엔진에서 클래스 추가

99.Define 필터 추가

엔진의 public폴더에 Engine_Define.h 추가

위에서 언급한 export와 import를 ifdef를 통해 구현

엔진의 프로젝트 속성 -> 전처리기 -> 전처리기 정의 내가 만든 프로젝트에_EXPORTS를 붙여서 자동으로 정의해줌 ( 라이브러리 프로젝트에서만)

이제 Base.h 에서 _declspec(dllexport) 를 ENGINE_DLL으로 변경해주면 된다.

  1. 클라이언트프로젝트에서 CBase를 디버그할수있으나 엔진의 cpp가 변경되면 디버그 불가 lib를 업데이트 해줘야함

FrameWork 폴더에 UpdateLib.bat 파일 생성
bat는 콘솔명령어를 그대로 실행해주는 파일
xcopy (복사) /y (덮어쓰겠다) .소스경로 .도착경로

xcopy /y .\Engine\public*.h .\Reference\Inc\ (퍼블릭 폴더안에 있는 모든 헤더 파일을 레퍼런스에 인클루드 폴더로 복붙해라)

xcopy /y .\Engine\public*.lib .\Reference\lib\

xcopy /y .\Engine\public*.dll .\Client\bin\

엔진이 수정됬다면 -> 빌드후 -> 배치파일실행

0개의 댓글

관련 채용 정보