在 Windows 下用 TDM-GCC(MinGW)開發 DLL 如果要用到數據同步鎖,理論上可以采用 Windows API 提供的臨界區實現(需要用到的函數有 InitializeCriticalSection、DeleteCriticalSection、EnterCriticalSection、LeaveCriticalSection),也可以采用 GCC 的 pthread 庫中的 pthread mutex lock 互斥鎖來實現(需要用到的函數有 pthread_mutex_init、pthread_mutex_destroy、pthread_mutex_lock、pthread_mutex_unlock)。但是在實際開發過程中發現,用 Windows API 的臨界區實現數據同步,會導致 DLL 運行失敗,目前原因還不明。無奈之下,改用 pthread 互斥鎖實現數據同步。pthread 本身是跨平台的,編譯鏈接時,使用 -lpthread 參數,預綁定到 pthread 的動態庫,測試發現 DLL 運行良好。後來用 objdump 分析生成的 DLL,發現使用 pthread 互斥鎖時,DLL 並沒有真正引用 pthread 的庫以及有關函數,所以猜測可能 pthread 針對 Windows 平台是采用 Windows API 提供的其他機制實現了互斥鎖效果吧。
另外發現一點,TDM-GCC(MinGW)開發 DLL 時,仍然可以使用 GCC 特有的動態庫(共享庫)初始化、終止化函數機制,比如下面這樣:
1 void __attribute__((constructor)) dynamic_library_init() { 2 pthread_mutex_init(&_ptm_mutex, NULL); 3 printf("dll _init() called OK\n"); 4 } 5 6 void __attribute__((destructor)) dynamic_library_fini() { 7 pthread_mutex_destroy(&_ptm_mutex); 8 printf("dll _fini() called OK\n"); 9 }
上面的 dynamic_library_init() 和 dynamic_library_fini() 是我自定義的函數名,你可以改為其他名字。因為默認的 _init() 和 _fini() 這兩個初始化、終止化函數已經 GCC 占用,我們無法使用,所以必須通過 GCC 擴展機制定義自己的動態庫、共享庫初始化終止化函數。這樣就可以避免在 Windows 下使用 DLLMain 機制,實現源代碼級跨平台支持,將需要在 DLL 載入初始化或卸載終止化時執行的重要操作放在這兩個函數裡面。