1. __declspec(dllexport) 를 사용하여 함수를 export 해야한다 ?
이것은 MS에서 만든 키워드로 unix/linux에는 사용할 수 없는 코드이다. 아래와 같이 구분하여 정의를 해준다.
#ifdef _WIN32 # define EXPORT_API(ret_type) __declspec(dllexport) ret_type #else //WIN32 # define EXPORT_API(ret_type) ret_type #endif //WIN32 EXPORT_API(int) EncodeBase64(const char* in_str, char* out_str, size_t* out_size) { ..... }
2. def 파일로 define을 해주어야 한다? extern "C"는 C코드에서 사용하기 위해서 넣어진 코드이다?
_declspec(dllexport)를 사용하면 def 파일을 따로 만들어주지 않아도 함수가 export 된다. 하지만 depends 로 보면 아래와 같이 name mangling 이 적용된다.
C++에서 import 할거면 이대로 좋은거라 생각하고 Loadlibrary와 GetProcAddress를 이용하여 로드 하였으나 Error code 0x7f (ERROR_PROC_NOT_FOUND) 를 내놓는다. GetProcAddress로는 C type 의 name만을 콜할 수 있고 mangling된 풀네임으로 콜 할 수는 있다.
GetProcAddress("EncodeBase64@@YAHPBDP...") (앞에 ?를 붙여야되나?? ㅎ)
그러므로 extern "C"를 해주거나 def 파일을 정의해주어서 mangling을 피한다. Visual C++ compiler에서는 원래 C 코드로 컴파일하도록 설정(c/c++->고급->컴파일옵션) 하여 이를 대신할 수도 있다. extern C는 C++에서만 사용할 수 있는 코드로 C 코드로 컴파일시는 extern "C"가 [Error C2059 구문 오류 : 문자열] 이란 에러를 생성한다.
결론적으로 아래와 같은 선언문 하나면 def 파일이나 C 코드로 컴파일 옵션 없이 export가 된다.
#ifdef __cplusplus # define EXTERN_C extern "C" #else # define EXTERN_C #endif #ifdef _WIN32 # define EXPORT_API(ret_type) EXTERN_C __declspec(dllexport) ret_type __stdcall #else //WIN32 # define EXPORT_API(ret_type) EXTERN_C ret_type #endif //WIN32
**__stdcall과 __cdecl중 무엇을 사용해야하는지는 선택이며 caller가 맞는 형식으로 로드하면 된다. [Name Mangling 과 calling convention] 을 참고한다.
depends로 본 결과는 아래와 같다.
그런데 이기종은 def파일을 사용해야하는건가? 이건또 다음에 정리~
이제 caller에서는
typedef int ( __stdcall *PFN_ENCODEBASE64)(const char* in_str, char* out_str, size_t& out_size);
m_pfnEncodebase64 = (PFN_ENCODEBASE64) GetProcAddress(m_hModule, "EncodeBase64");
이렇게 dynamic load 시 함수포인터 얻는다~
댓글 없음:
댓글 쓰기