--------------------Configuration: curl - Win32 LIB Debug DLL Windows SSPI DLL WinIDN-------------------- xilink6: executing 'D:\vc6.0\VC98\Bin\link.exe' libcurld.lib(idn_win32.obj) : error LNK2001: unresolved external symbol __imp__IdnToAscii@20 libcurld.lib(idn_win32.obj) : error LNK2001: unresolved external symbol __imp__IdnToUnicode@20 ..\..\..\..\build\Win32\VC6\LIB Debug - DLL Windows SSPI - DLL WinIDN\curld.exe : fatal error LNK1120: 2 unresolved externals Error executing xilink6.exe. curld.exe - 3 error(s), 2 warning(s) --------------------Configuration: curl - Win32 LIB Release DLL Windows SSPI DLL WinIDN-------------------- Linking... xilink6: executing 'D:\vc6.0\VC98\Bin\link.exe' libcurl.lib(idn_win32.obj) : error LNK2001: unresolved external symbol __imp__IdnToAscii@20 libcurl.lib(idn_win32.obj) : error LNK2001: unresolved external symbol __imp__IdnToUnicode@20 ..\..\..\..\build\Win32\VC6\LIB Release - DLL Windows SSPI - DLL WinIDN/curl.exe : fatal error LNK1120: 2 unresolved externals
根據兩個API的名字google了一下windows
IdnToUnicode,IdnToAscii封裝在normaliz.dll中,查詢了本機的幾個SDK(Microsoft Platform SDK February 2003,Microsoft Windows SDK v6.0A,Microsoft Windows SDK v7.0A,
Microsoft Windows SDK v7.1),只有Microsoft Platform SDK February 2003沒有,心想這下壞了,很差編譯了,由於Microsoft Platform SDK February 2003是Windows XP最終版SDK,翻了一下%systemroot%\system32\又能夠找到normaliz.dll,查看了一下導出函數,又是有的,不懂什麼軟件帶過來的,仍是系統更新裝上的。
msdn對IdnToUnicode,IdnToAscii這兩個函數的使用要求以下:
Minimum supported clientapp |
Windows Vista [desktop apps | Windows Store apps]less |
---|---|
Minimum supported servercurl |
Windows Server 2008 [desktop apps | Windows Store apps]函數 |
Redistributableui |
Microsoft Internationalized Domain Name (IDN) Mitigation APIs onWindows XP with SP2 and later,Windows Server 2003 with SP1google |
Headerurl |
|
Libraryspa |
|
DLLdebug |
|
從以上表格看出,這個庫一開始並非爲Windows XP準備的,只是後來在SP2之後纔有,用VC++6.0編譯的時候normaliz.lib指向的dll函數地址就是錯誤的,
因而想到用LoadLibrary和GetProcAddress函數配合,顯式調用者兩個函數,從這個程度上來講也能夠節省內存開銷,使用完當即釋放掉。
問題的根源是idn,因而找到了CURL_FOLDER\lib\idn_win32.c進行開刀。
如下是7.50.3版本的idn_win32.c修改前的模樣:
#include "curl_setup.h" #ifdef USE_WIN32_IDN #include "curl_multibyte.h" #include "curl_memory.h" #include "warnless.h" /* The last #include file should be: */ #include "memdebug.h" #ifdef WANT_IDN_PROTOTYPES # if defined(_SAL_VERSION) WINNORMALIZEAPI int WINAPI IdnToAscii(_In_ DWORD dwFlags, _In_reads_(cchUnicodeChar) LPCWSTR lpUnicodeCharStr, _In_ int cchUnicodeChar, _Out_writes_opt_(cchASCIIChar) LPWSTR lpASCIICharStr, _In_ int cchASCIIChar); WINNORMALIZEAPI int WINAPI IdnToUnicode(_In_ DWORD dwFlags, _In_reads_(cchASCIIChar) LPCWSTR lpASCIICharStr, _In_ int cchASCIIChar, _Out_writes_opt_(cchUnicodeChar) LPWSTR lpUnicodeCharStr, _In_ int cchUnicodeChar); # else WINBASEAPI int WINAPI IdnToAscii(DWORD dwFlags, const WCHAR *lpUnicodeCharStr, int cchUnicodeChar, WCHAR *lpASCIICharStr, int cchASCIIChar); WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags, const WCHAR *lpASCIICharStr, int cchASCIIChar, WCHAR *lpUnicodeCharStr, int cchUnicodeChar); # endif #endif #define IDN_MAX_LENGTH 255 bool curl_win32_idn_to_ascii(const char *in, char **out); bool curl_win32_ascii_to_idn(const char *in, char **out); bool curl_win32_idn_to_ascii(const char *in, char **out) { bool success = FALSE; wchar_t *in_w = Curl_convert_UTF8_to_wchar(in); if(in_w) { wchar_t punycode[IDN_MAX_LENGTH]; int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH); free(in_w); if(chars) { *out = Curl_convert_wchar_to_UTF8(punycode); if(*out) success = TRUE; } } return success; } bool curl_win32_ascii_to_idn(const char *in, char **out) { bool success = FALSE; wchar_t *in_w = Curl_convert_UTF8_to_wchar(in); if(in_w) { size_t in_len = wcslen(in_w) + 1; wchar_t unicode[IDN_MAX_LENGTH]; int chars = IdnToUnicode(0, in_w, curlx_uztosi(in_len), unicode, IDN_MAX_LENGTH); free(in_w); if(chars) { *out = Curl_convert_wchar_to_UTF8(unicode); if(*out) success = TRUE; } } return success; } #endif /* USE_WIN32_IDN */
idn_win32.c修改後的模樣:
#include "curl_setup.h" #ifdef USE_WIN32_IDN #include "curl_multibyte.h" #include "curl_memory.h" #include "warnless.h" /* The last #include file should be: */ #include "memdebug.h" #ifdef WANT_IDN_PROTOTYPES //# if defined(_SAL_VERSION) typedef int (*fnIdnToAscii)(DWORD,const WCHAR *,int,WCHAR *,int); typedef int (*fnIdnToUnicode)(DWORD,const WCHAR *,int,WCHAR *, int); //# endif #endif #define IDN_MAX_LENGTH 255 bool curl_win32_idn_to_ascii(const char *in, char **out); bool curl_win32_ascii_to_idn(const char *in, char **out); bool curl_win32_idn_to_ascii(const char *in, char **out) { bool success = FALSE; wchar_t *in_w = Curl_convert_UTF8_to_wchar(in); if(in_w) { wchar_t punycode[IDN_MAX_LENGTH]; int chars = -1; fnIdnToAscii IdnToAscii; HINSTANCE hNormalizDLL = LoadLibrary("normaliz.dll"); if (!hNormalizDLL) { FreeLibrary(hNormalizDLL); assert(hNormalizDLL); return FALSE; } IdnToAscii = (fnIdnToAscii)GetProcAddress(hNormalizDLL, "IdnToAscii"); if (!IdnToAscii) { assert(IdnToAscii); return TRUE; } chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH); free(IdnToAscii); FreeLibrary(hNormalizDLL); free(in_w); if(chars) { *out = Curl_convert_wchar_to_UTF8(punycode); if(*out) success = TRUE; } } return success; } bool curl_win32_ascii_to_idn(const char *in, char **out) { bool success = FALSE; wchar_t *in_w = Curl_convert_UTF8_to_wchar(in); if(in_w) { size_t in_len = wcslen(in_w) + 1; wchar_t unicode[IDN_MAX_LENGTH]; int chars = -1; fnIdnToUnicode IdnToUnicode; HINSTANCE hNormalizDLL = LoadLibrary("normaliz.dll"); if (!hNormalizDLL) { FreeLibrary(hNormalizDLL); assert(hNormalizDLL); return FALSE; } IdnToUnicode = (fnIdnToUnicode)GetProcAddress(hNormalizDLL, "IdnToUnicode"); if (!IdnToUnicode) { assert(IdnToUnicode); return FALSE; } chars = IdnToUnicode(0, in_w, curlx_uztosi(in_len), unicode, IDN_MAX_LENGTH); free(IdnToUnicode); FreeLibrary(hNormalizDLL); free(in_w); if(chars) { *out = Curl_convert_wchar_to_UTF8(unicode); if(*out) success = TRUE; } } return success; } #endif /* USE_WIN32_IDN */
通過以上修改就能夠編譯成功了。