錯誤重現:
--------------------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了一下
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 client |
Windows Vista [desktop apps | Windows Store apps] |
|---|---|
| Minimum supported server |
Windows Server 2008 [desktop apps | Windows Store apps] |
| Redistributable |
Microsoft Internationalized Domain Name (IDN) Mitigation APIs onWindows XP with SP2 and later,Windows Server 2003 with SP1 |
| Header |
|
| Library |
|
| DLL |
|
從以上表格看出,這個庫一開始並不是為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 */
經過以上修改就可以編譯成功了。
1. 遇到如下問題
1>libcurl.lib(easy.obj) : error LNK2001: 無法解析的外部符號 __imp_WSAStartup
1>libcurl.lib(telnet.obj) : error LNK2001: 無法解析的外部符號 __imp_WSAStartup
1>libcurl.lib(easy.obj) : error LNK2001: 無法解析的外部符號 __imp_WSACleanup
1>libcurl.lib(telnet.obj) : error LNK2001: 無法解析的外部符號 __imp_WSACleanup
1>libcurl.lib(ftp.obj) : error LNK2001: 無法解析的外部符號 __imp_WSAGetLastError
1>libcurl.lib(telnet.obj) : error LNK2001: 無法解析的外部符號 __imp_WSAGetLastError
1>libcurl.lib(tftp.obj) : error LNK2001: 無法解析的外部符號 __imp_WSAGetLastError
1>libcurl.lib(asyn-thread.obj) : error LNK2001: 無法解析的外部符號 __imp_WSAGetLastError
1>libcurl.lib(select.obj) : error LNK2001: 無法解析的外部符號 __imp_WSAGetLastError
1>libcurl.lib(sendf.obj) : error LNK2001: 無法解析的外部符號 __imp_WSAGetLastError
1>libcurl.lib(connect.obj) : error LNK2001: 無法解析的外部符號 __imp_WSAGetLastError
1>libcurl.lib(select.obj) : error LNK2001: 無法解析的外部符號 __WSAFDIsSet
1>libcurl.lib(select.obj) : error LNK2001: 無法解析的外部符號 __imp_select
1>libcurl.lib(select.obj) : error LNK2001: 無法解析的外部符號 __imp_WSASetLastError
1>libcurl.lib(connect.obj) : error LNK2001: 無法解析的外部符號 __imp_WSASetLastError
1>libcurl.lib(curl_addrinfo.obj) : error LNK2001: 無法解析的外部符號 __imp_WSASetLastError
1>libcurl.lib(sendf.obj) : error LNK2001: 無法解析的外部符號 __imp_recv
1>libcurl.lib(connect.obj) : error LNK2001: 無法解析的外部符號 __imp_recv
1>libcurl.lib(sendf.obj) : error LNK2001: 無法解析的外部符號 __imp_send
1>libcurl.lib(telnet.obj) : error LNK2001: 無法解析的外部符號 __imp_send
1>libcurl.lib(connect.obj) : error LNK2001: 無法解析的外部符號 __imp_bind
1>libcurl.lib(ftp.obj) : error LNK2001: 無法解析的外部符號 __imp_bind
1>libcurl.lib(tftp.obj) : error LNK2001: 無法解析的外部符號 __imp_bind
1>libcurl.lib(connect.obj) : error LNK2001: 無法解析的外部符號 __imp_closesocket
1>libcurl.lib(connect.obj) : error LNK2001: 無法解析的外部符號 __imp_connect
1>libcurl.lib(connect.obj) : error LNK2001: 無法解析的外部符號 __imp_getpeername
1>libcurl.lib(connect.obj) : error LNK2001: 無法解析的外部符號 __imp_getsockname
1>libcurl.lib(ftp.obj) : error LNK2001: 無法解析的外部符號 __imp_getsockname
1>libcurl.lib(connect.obj) : error LNK2001: 無法解析的外部符號 __imp_getsockopt
1>libcurl.lib(smb.obj) : error LNK2001: 無法解析的外部符號 __imp_htons
1>libcurl.lib(connect.obj) : error LNK2001: 無法解析的外部符號 __imp_htons
1>libcurl.lib(curl_addrinfo.obj) : error LNK2001: 無法解析的外部符號 __imp_htons
1>libcurl.lib(ftp.obj) : error LNK2001: 無法解析的外部符號 __imp_htons
1>libcurl.lib(telnet.obj) : error LNK2001: 無法解析的外部符號 __imp_htons
1>libcurl.lib(connect.obj) : error LNK2001: 無法解析的外部符號 __imp_ntohs
1>libcurl.lib(ftp.obj) : error LNK2001: 無法解析的外部符號 __imp_ntohs
1>libcurl.lib(connect.obj) : error LNK2001: 無法解析的外部符號 __imp_setsockopt
1>libcurl.lib(connect.obj) : error LNK2001: 無法解析的外部符號 __imp_socket
1>libcurl.lib(connect.obj) : error LNK2001: 無法解析的外部符號 __imp_WSAIoctl
1>libcurl.lib(curl_addrinfo.obj) : error LNK2001: 無法解析的外部符號 __imp_getaddrinfo
1>libcurl.lib(curl_addrinfo.obj) : error LNK2001: 無法解析的外部符號 __imp_freeaddrinfo
1>libcurl.lib(ftp.obj) : error LNK2001: 無法解析的外部符號 __imp_accept
1>libcurl.lib(ftp.obj) : error LNK2001: 無法解析的外部符號 __imp_listen
1>libcurl.lib(tftp.obj) : error LNK2001: 無法解析的外部符號 __imp_recvfrom
1>libcurl.lib(tftp.obj) : error LNK2001: 無法解析的外部符號 __imp_sendto
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ldap_init
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ldap_unbind_s
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ldap_set_option
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ldap_simple_bind_s
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ldap_search_s
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ldap_msgfree
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ldap_err2string
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ldap_first_entry
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ldap_next_entry
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ldap_first_attribute
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ldap_next_attribute
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ldap_get_values_len
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ldap_value_free_len
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ldap_get_dn
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ldap_memfree
1>libcurl.lib(ldap.obj) : error LNK2001: 無法解析的外部符號 __imp_ber_free
1>libcurl.lib(nonblock.obj) : error LNK2001: 無法解析的外部符號 __imp_ioctlsocket
具體步驟就是:
給工程添加依賴的庫:項目->屬性->鏈接器->輸入->附加依賴項,把 ws2_32.lib、 winmm.lib、 wldap32.lib添加進去
注意,debug配置用libcurld.lib
2.如出現
error LNK2001: 無法解析的外部符號 __imp_curl_easy_perform
error LNK2001: 無法解析的外部符號 __imp_curl_easy_init
error LNK2001: 無法解析的外部符號 __imp_curl_slist_append
error LNK2001: 無法解析的外部符號 __imp_curl_slist_free_all
error LNK2001: 無法解析的外部符號 __imp_curl_easy_cleanup
error LNK2001: 無法解析的外部符號 __imp_curl_easy_setopt
加入預編譯選項:項目->屬性->c/c++ ->預處理器->預處理器,把 BUILDING_LIBCURL;HTTP_ONLY復制進去(注意不要丟了";")
3.如出現
1>libcurl.lib(cookie.obj) : error LNK2001: 無法解析的外部符號 __imp_fgets
1>libcurl.lib(netrc.obj) : error LNK2001: 無法解析的外部符號 __imp_fgets
1>libcurl.lib(mime.obj) : error LNK2001: 無法解析的外部符號 __imp_access
1>OLDNAMES.lib(access.obi) : error LNK2001: 無法解析的外部符號 __imp_access
1>libcurl.lib(tftp.obj) : error LNK2001: 無法解析的外部符號 __imp_strstr
1>libcurl.lib(digest.obj) : error LNK2001: 無法解析的外部符號 __imp_strstr
1>libcurl.lib(ftplistparser.obj) : error LNK2001: 無法解析的外部符號 __imp_strstr
1>libcurl.lib(url.obj) : error LNK2001: 無法解析的外部符號 __imp_strstr
1>libcurl.lib(http.obj) : error LNK2001: 無法解析的外部符號 __imp_strstr
1>libcurl.lib(transfer.obj) : error LNK2001: 無法解析的外部符號 __imp_strstr
1>libcurl.lib(ftp.obj) : error LNK2001: 無法解析的外部符號 __imp_strstr
1>libcurl.lib(warnless.obj) : error LNK2001: 無法解析的外部符號 __imp_read
1>OLDNAMES.lib(read.obi) : error LNK2001: 無法解析的外部符號 __imp_read
1>libcurl.lib(warnless.obj) : error LNK2001: 無法解析的外部符號 __imp_write
1>OLDNAMES.lib(write.obi) : error LNK2001: 無法解析的外部符號 __imp_write
1>libcurl.lib(parsedate.obj) : error LNK2001: 無法解析的外部符號 __imp__gmtime64
1>libcurl.lib(file.obj) : error LNK2001: 無法解析的外部符號 __imp_open
1>OLDNAMES.lib(open.obi) : error LNK2001: 無法解析的外部符號 __imp_open
1>libcurl.lib(smb.obj) : error LNK2001: 無法解析的外部符號 __imp__getpid
1>libcurl.lib(system_win32.obj) : error LNK2001: 無法解析的外部符號 __imp__mbspbrk
這個問題 :要 統一代碼生成方式,如果是 Debug 就是多線程調試 /MTd,如果是 Release 就是多線程 /MT
C/C++ -> 代碼生成 -> 運行庫
curl 工程默認是MD ,改成MT就可以了。
4.libcurl出現CURLcode 23 CURLE_WRITE_ERROR錯誤
百度了下是 write_func 回調函數有問題 ,
因為我編譯的是全平台的,windows、linux 系統接口是不同的,回調函數需要定義成不現的函數
#if defined(WIN32) || defined(_WIN32) || defined(WINDOWS)
size_t write_func(char *ptr, size_t size, size_t nmemb, void *userdata) //回調函數
{
std::string &buffer = *(std::string *) userdata;
size_t len = size * nmemb;
for (size_t i = 0; i < len; ++i) {
buffer += *ptr;
++ptr;
}
// LOGE(buffer.c_str());
return len;
}
#else
void write_func(char *ptr, size_t size, size_t nmemb, void *userdata) //回調函數
{
std::string &buffer = *(std::string *) userdata;
size_t len = size * nmemb;
for (size_t i = 0; i < len; ++i) {
buffer += *ptr;
++ptr;
}
// LOGE(buffer.c_str());
}
#endif
原文鏈接:https://blog.csdn.net/q610098308/java/article/details/88569866

