declspec에 대해

declspec에 대해

동기

C#의 Getter/Setter 프로퍼티를 C++에서 쓰고 싶어짐
define을 응용을 어떻게 해야될지를 고민

계획

1. 일단 내 머리로는 안되겠다. 도움이 될만한 사이트를 찾아서 검색!
2. 찾아보니 declspec와 property를 사용하면 손쉽게 만들 수 있다고 한다.
3. declspec와 property를 알아보자.

declspce란?

형식

_declspec (extened -attrubute) declarator

정의

함수에 대한 정보를 제공하는 선언문.

  • 기억부류 (storage class)에 관한 정보를 단순환, 표준화하는 역할을 한다.
  • 표준 C++문법은 아니며 MS에서 만든 확장 문법이다.
  • 그렇기에 함수와 비슷한 형태를 보이지만, 키워드에 속한다.

표준 C++이 아니기에 VS Code에서 declspec를 사용하면 에러가 뜬다. 테스트 코드를 VS code에서 실행했더니 계속 컴파일 단계에서 에러가 뜨더라;;


property

클래스의 비정적 가상 데이터 멤버에 사용할 수 있으며, 이 속성이 지정되고 이 변수에 포인터 멤버 선택 연산자(->)를 사용하여 참조할 때, 컴파일러는 이들에 대하여 대응되는 함수 호출로 변경한다.

원형

__declspec(property(get=Getname, put=Putname)) _bstr_t_name

위의 __declspec(property) 확장 속성은 ->와 함께 name식별자가 rvalue(right value)로 사용될 때, Getname함수를 호출하고, lvalue(left value)로 사용될 때는 Putname함수를 호출한다.

C#의 Getter/Setter 프로퍼티 흉내내기

이 property 속성을 이용해서 Getter/Setter를 C++에서 흉내낼 수 있다.
코드만 보면 설명이 필요없을 것같아서, 쓰지 않겠습니다.

#define PROPERTY(_get, _set) _declspec(property(get = _get, put = _set))
#define G_PROPERTY(_get) _declspec(property(get = _get))
#define S_PROPERTY(_set) _declspec(property(set = _set))

class TestObject
{
public:
    int GetInt() { return m_i; }
    void SetInt(int i) { m_i = i; }

    PROPERTY(GetInt, SetInt) int i;

private:
    int m_i;
};

int main()
{
    TestObject ob;

    ob.i = 100;
    printf("i : %d \n", ob.i);

    return 0;
}

단점

Getter/Setter 함수가 public으로 선언되어있다. 굳이 두 번 선언할 이유가 있을까? 편리하게 사용할 수는 있지만...

참조한 포스트

다음의 포스트를 참조했다.

_declspec()


dll의 Export와 Import

declspec의 속성중 하나로 property를 알아보다가 얼떨결에 같이 공부했다.

exe파일을 실행시키면 필요한 라이브러리들이 따라 붙게된다. 그때에 붙는 라이브러리들이 dll이다. dll안에는 exe파일에서 필요한 함수들이 정의되어있다. 이 dll을 만들 때에 _declspec를 사용한다.


__declspec(dlliexport) //정의된 함수를 외부에서 사용할 수 있는 형태로 만들겠다.
void DLL_PrintFunction()
{
    //...
}

__declspec(dllimport) // 선언된 함수를 DLL로부터 제공받겠다.
void DLL_PrintFuncion();

dllimport의 작동원리

우연히 DLL의 import의 작동원리를 설명한 포스트를 보았다. 알면 좋겠다고 생각해서 같이 쓰겠다.

내가 처음 dll을 만들고 사용할 때에, declspec 키워드를 쓰지 않았음에도 include하여 사용한 기억이 있다. 이유는 링커가 해당 함수를 dll의 함수를 호출할 수 있도록 컴파일 시점에서 연결시켜주기 때문이다. (단 헤더파일에 정의한 경우에서만 해당된다.)
즉 다른 모듈에서 제공되는 함수를 호출하는데 있어서 함수에 declspec을 선언하지 않아도 DLL에서 제공된 함수를 사용할 수 있다.
심지어, 이것은 디스어셈블리 단위에서 보면 선언하지 않은 것이 더 빠르다.

    Export_Print();     //declspec를 사용하지 않은 경우
0097187B  call        Export_Print (09710AFh)  

00BA16EC  rep stos    dword ptr es:[edi]  
    DllExport_Print();  //declspec를 사용한 경우
00BA16EE  mov         esi,esp  
00BA16F0  call        dword ptr [__imp_DllExport_Print (0BAA098h)]

보다시피, 사용한 경우에 mov가 하나 더 실행되는 것을 알 수 있다. cpp에 정의할 경우에 mov 명령이 하나 더 추가되는 것을 감안하고 사용하는 것이 좋을 것같다.

참조한 포스트

이것에 대해서는 다음 포스트의 도움을 받았다.

DLL 만들어보기
__declspec(dllimport)의 호출 원리


'프로그래밍 > 프로그래밍 관련' 카테고리의 다른 글

Epoll  (0) 2018.03.22
함수포인터로 함수명 변경하기  (0) 2018.03.22
RAII (1)  (0) 2018.01.28
VS Code로 C++ 디버깅  (0) 2018.01.25
GitHub와 VS의 연동 문제  (0) 2018.01.23
더보기

댓글,

Lowpoly

게임 서버 프로그래머 지망생