http://blog.naver.com/kimgudtjr?Redirect=Log&logNo=140096145411 에서 인용한글
위에서는.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" 키워드를 꼭 붙인다고 한다.
------------------------------------------------------------------
이렇게 함수이름을 어떤 형식으로 짓냐는 방법을
이름 데콜이션 이라고 한다.. 그 규칙이 버전별로 조금씩 다른데....................
독자는 귀찮아서.. 그냥 이 부분은 넘기려고 한다. -_-ㅋ
'운영체제 & 병렬처리 > DLL_LIB' 카테고리의 다른 글
static 멤버 변수를 dllexport 하려면? (0) | 2012.11.01 |
---|---|
Dllexport 시 멤버 변수 선언하는 방법 (0) | 2012.11.01 |
DLL 생성과 익스포트 섹션1 (0) | 2012.11.01 |
함수포인터와 DLL, 함수 포인터를 써야 하는 상황 (0) | 2012.11.01 |
static 변수,함수에서 접근할때 변수 초기위치와 DLL (0) | 2012.11.01 |