zoukankan      html  css  js  c++  java
  • 解决libcurl7.50.3在windows XP SP3 VC++ 6.0下编译报错 unresolved external symbol __imp__IdnToAscii@20 unresolved external symbol __imp__IdnToUnicode@20

    错误重现:

    --------------------Configuration: curl - Win32 LIB Debug DLL Windows SSPI DLL WinIDN--------------------
    
    xilink6: executing 'D:vc6.0VC98Binlink.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
    ........uildWin32VC6LIB Debug - DLL Windows SSPI - DLL WinIDNcurld.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.0VC98Binlink.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
    ........uildWin32VC6LIB 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

    Winnls.h (include Windows.h)

    Library

    Normaliz.lib

    DLL

    Normaliz.dll
      从以上表格看出,这个库一开始并不是为Windows XP准备的,只是后来在SP2以后才有,用VC++6.0编译的时候normaliz.lib指向的dll函数地址就是错误的,
    于是想到用LoadLibrary和GetProcAddress函数配合,显式调用者两个函数,从这个程度上来说也可以节省内存开销,使用完立即释放掉。

    解决办法:

    问题的根源是idn,于是找到了CURL_FOLDERlibidn_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 */
     经过以上修改就可以编译成功了。
  • 相关阅读:
    lnmp一键安装包,安装多版本php,并开启redis与swoole
    wangEditor的使用
    记一次傻逼的录入
    PHP自动加载
    pip升级
    Ubuntu安装mycli,让mysql命令行可以自动提示
    Redis存储AccessToken
    微信小程序生成太阳码
    巧妙的新订单提醒功能
    使用pt-query-digest进行日志分析
  • 原文地址:https://www.cnblogs.com/passedbylove/p/5979927.html
Copyright © 2011-2022 走看看