1>afc_scm.obj : warning LNK4197: export 'send_command' specified multiple times; using first specification 1>afc_scm.obj : warning LNK4197: export 'stop_driver' specified multiple times; using first specification 1>afc_scm.obj : warning LNK4197: export 'start_driver' specified multiple times; using first specification 1>afc_scm.obj : warning LNK4197: export 'uninstall_driver' specified multiple times; using first specification 1>afc_scm.obj : warning LNK4197: export 'install_driver' specified multiple times; using first specification 1>afc_scm.obj : warning LNK4197: export 'free_scm_context' specified multiple times; using first specification 1>afc_scm.obj : warning LNK4197: export 'create_scm_context' specified multiple times; using first specification32비트에서는 아무런 문제없이 빌드되던 프로젝트가 오늘 보니 4197 링크 경고를 뿌려대고 있었습니다.
http://support.microsoft.com/kb/835326/en-us 페이지에 경고에 대해서 설명된 내용이 있네요.
결론은 dllexport 를 사용하던지 def 파일을 사용하던지 하나만 하라는건데요...
문제가 좀 있어보입니다.
def 파일을 사용하지 않고, __declspec(dllexport) 만 사용하는 경우 __stdcall 호출방식을 사용할때 네임맹글링 문제로 인해서 원치않는 형태의 이름으로 export 되지요.
아래 그림처럼요...
그렇다면 def 파일을 이용해서 dll export 를 하면어떨까요?
이건 제 경우에만 문제가 될 수 있는 문제인데요. 저는 dll 을 만들때 아래와 같은 구조의 코드를 항상 사용합니다.
#ifdef AFC_SCM_EXPORTS #ifdef __cplusplus #define AFC_SCM_API extern "C" __declspec(dllexport) #define AFC_SCM_CLASS __declspec(dllexport) #else #define AFC_SCM_API __declspec(dllexport) #endif//__cplusplus #else #ifdef __cplusplus #define AFC_SCM_API extern "C" __declspec(dllimport) #define AFC_SCM_CLASS __declspec(dllimport) #else #define AFC_SCM_API __declspec(dllimport) #endif//__cplusplus #endif//AFC_SCM_EXPORTS AFC_SCM_API scm_ctx __stdcall create_scm_context( _In_z_ const wchar_t* driver_path, _In_z_ const wchar_t* service_name, _In_z_ const wchar_t* service_display_name, _In_ bool uninstall_service_on_free );AFC_SCM_API 가 정의되어있는 경우 (dll 프로젝트 자체) create_scm_context() 함수는 dllexport 가 됩니다. 그렇지 않은 경우 create_scm_context() 함수는 dllimport 가 되죠. 즉 dll 을 묵시적으로 링크하는 프로젝트가 되겠죠.
dll 사용자는 dll, lib, header 파일만 있으면 별도로 손대지 않고, 그냥 dll 을 나름 편하게 사용할 수 있습니다. def 파일을 이용해서 dll 을 만드는 경우 이런 이점을 버려야 할것 같네요. (별도로 dllimport 를 해주거나 명시적 링킹을 해야 하니까요...)
대체 MS 는 왜 이런 짓을 하는거야..ㅆㅂ ㅆㅂ 하면서 잠시 생각해보니 나이스한 해결책이 있습니다. ( 사실은 해결책이 아니라 제가 바보였던거죠. )
x86 프로젝트에서는 예전처럼 dllexport 와 DEF 파일을 모두 사용하고, x64 프로젝트에서는 def 만 사용안하면 그만입니다. x64 는 호출규약이 하나뿐이라 네임맹글링 문제가 없어서 def 와 dllexport 를 함께 사용하지 않도록 (불필요한 실수를 줄이기 위해) 가이드하는거 같습니다... (아님 말구요)
결론: dll 을 만들때는
- dllexport 를 이용하고,
- 32 비트에서 네임맹글링 문제가 있다면 def 파일을 함께 사용
- 64 비트에서는 그냥 dllexport 만 사용 (네임맹글링 문제가 아예 없다!)
댓글 없음:
댓글 쓰기