http://blog.naver.com/kimgudtjr?Redirect=Log&logNo=140096145411 에서 인용한글


[두번째 방법 : __declspec(dllexport) 지시자 사용방법 ]

위에서는.def 파일을 이용했는데 이 방식은 예전 16비트 시절부터 쓰던 옛발 방식이라고 한다..

여기서는 다은방법을 보자면. 해당 수출하려는 함수에 export 하려는 함수 앞에

__declspec(dllexport) 라는 키워드를 쓰면 된다고 한다. -_-ㅋ

근데 여기 책에서 설명하는 방법은 좀 복잡하고 요상하게 쓰는데 -_-ㅋ 일단 아래를 따라가보자..


여기서는 __declspec(dllexport) 를 쓸대  

1. __declspec(dllexport) 용 test.h 라는 헤더파일을 만든다.


2. __declspec(dllexport) 용 test.cpp 라는 함수 구현 파일을 만든다.


------------------ test.h ---------------------------

#ifndef __DLLBASIC_H__
#define __DLLBASIC_H__

#define DLLBASIC_API
#define DLLBASIC_API extern "C" __declspec(dllimport)

DLLBASIC_API int Sum(int a, int b);

#endif
  
------------------------------------------------------

위의 Sum 함수는 실제로 책에는 다른 함수로  되어있지만  책의 함수가 조금 복잡해서

독자가 이해하기 휩게 하기 위해 단순하게 바껏다.


----------- test.cpp --------------------
#define DLLBASIC_API extern "C" __declspec(dllexport)

#include "test.h"

int SumIint a, intb)
{
 return a+b;
}

------------------------------------------------------

책에서는 이렇게 사용한ㄷ고 되어있다..

사실 test.cpp위에 부분에 보면 DLLBASIC_API 를 먼저 정의하고 test.h 파일을 포함하기 때문에

test.h 파일에 있는 dllimport 는 아무 의미없이 되고 전부다 dllexport로 대체 될것이다.

근데 굳이 이렇게 해더 파일에는 dllimport 를 쓰고 cpp에는 dllexport를 써서 복잡하기 하는 이유가

독자는 너무 긍금했다.. 하지만 책에 잘 설명이 되어있었다.... 하지만 ..-_-ㅋ 보고도 이해를 잘 하지 못했따.. -=_-ㅋㅋ

일단 책에 나와있는 설명을 그대로 옮겨보겠지만.. 혹시라도  아시는분 있으면 알려주길 바란다....

--- 책의 설명.. --------

하지만 왜 이렇게 따로 전처리기 까지 사용해서 복잡하게 dllimport까지 지정하는 것일까???

후에 해당 DLL 사용 시 test.h를 인클루드하게 되면 별도의 DLLBASIC_API라는 매크로를 정의하지 않기 때문에

해당 DLL을 사용하는 입장에서의 DLLBASIC_API는 __declspec(dllimport)로 정의 된다. 그렇게 되면 자연스럽게 헤더에 선언된 함수가

임포트 할 함수임을 미리 컴파일러에게 알리는 역할을 한다. 물론 굳이 알리지 않아도 사용하는 데에는 전혀 문제가 없다.

하지만 이렇게 임포트 함수임을 미리 알리느냐 알리지 않느냐의 미묘한 차이는 실제 PE이미지가 생성될 때 조그만한 차이를 불러온다.

그 차이는 5장 DLL 로딩과 임포트 섹션에서 논의하도록 한다.

------------------------------------------------------------------------
라고 되어있다 -_-ㅋ 먼말인지 몰것다. 그냥 재꼈다 -_-ㅋ

그러면 해당 dll파일을 dumpbin /export test.dll 이라고 해서 확인해보자

글엄 export 된 함수들을 볼수 있다.. 다만 이경우에는

서수를 사용자 임의대로 붙일수 없다고 한다. ..

그래서 서수를 지정해서 사용하는 방법은 포기해야 한다고 한다 -_-ㅋ






[익스포트 함수명의 문제 함수 호출 방식 - 파스칼 방식 C선언 방식 ]


1. 예전엔 아래와 같이 함수 호출 방식이 2가지였다고 함.
   - 하나 : 파스칼방식 
   - 둘    : C선언 방식

2. VC++ 에서 이 두가지 방식의 스택 이용방식을 통일했다고 함.. 둘다 왼쪽에서 오른쪽으로.. ..
   스택이용방식에 있어선 파스칼 방식으로 채택....  
   스택제거 시점은 아직 구분했다고 했다고함.. 아래와 같이 ...


 -------------- C언선방식 -----------------

함수매개변수 : 매개변수를 오른쪽에서 왼쪽으로 스택에 push 한다.

스택제거      : 함수를 호출한 쪽에서 스택을 제거 한다

키워드 :    : __cdecl

아무것도 정의 안하면 디폴트로 C선언 방식으로 된다.
------------------------------------


 -------------- 파스칼방식 -----------------
 
함수매개변수 : 매개변수를 왼쪽에서 오른쪽으로 스택에 push한다.

스택제거     : 함수가 호출된 쪽에서 스택을 제거

키워드         :  __stdcall

_stdcall  또는 WINAPI 를 함수 앞에 쓰면 파스칼 방식으로 된다.
------------------------------------


그리고 자세히보면 위 코드에

#define DLLBASIC_API extern "C" __declspec(dllexport)

라고 되어 잇는데 extern "C" 를 유심히 보자..

이 부분을 제거하고 컴파일 한후  dumpbin /EXPORTS test.dll 한번해보고

이 부분을 제거 하지 말고  컴파일 한후 dumpbin /EXPORTS test.dll 해보라..

그러면 export 되는 함수 이름이 다를 것이다.

extern "C" 라는 키워드는 C언어 형식으로 함수 이름을 짓고

extern "C" 를 제거하면 C++ 규칙대로 함수 이름을 짓는다..

extern "C" 방식은 모든 컴파일러에서 알아볼수 있는 형식이므로

extern "C" 방식으로 함수를 작성하면 다른 컴퓨터에서 무리 없이 돌아가지만

extern "C"를 제거한 C++ 방식으로 함수를 작성하면

함수이름이 이상하게 변하는데 그 이상하게 변환하는 규칙이 각각 컴파일러 마다

제각각이여서 다른 컴퓨터와 호환이 되지 않는다..

그래서 함수를 export 하고자 할때는 위의 extern "C" 키워드를 꼭 붙인다고 한다.

------------------------------------------------------------------

이렇게 함수이름을 어떤 형식으로 짓냐는 방법을

이름 데콜이션 이라고 한다.. 그 규칙이 버전별로 조금씩 다른데....................

독자는 귀찮아서.. 그냥 이 부분은 넘기려고 한다. -_-ㅋ

반응형

+ Recent posts