0

我正在开发一个 C++/WinRT 项目,并希望在其中使用 Boost (1.73.0) 语言环境。受Microsoft 博客文章的启发,我已经替换了对库源中不受支持的 WinApi 函数的调用,并使用windows-api=store. 我设法构建了所有预期的库变体(arm / x64,debug / release)并继续构建 UWP 应用程序。这就是我现在卡住的地方。构建无法与以下输出链接:

vccorlibd.lib(init.obj):错误 LNK2038:检测到“vccorlib_lib_should_be_specified_before_msvcrt_lib_to_linker”不匹配:值“1”与 MSVCRTD.lib(app_appinit.obj) 中的值“0”不匹配

vccorlibd.lib(init.obj):错误 LNK2005:__crtWinrtInitType 已在 MSVCRTD.lib(app_appinit.obj) 中定义

触发失败的行:

const auto text = boost::locale::conv::to_utf<char>("xxx", "yyy");

我的设置是 Visual Studio 17 和 19,SDK 10.0.19041.0。我已经尝试过针对类似问题提出的解决方案,但无济于事。我在boost_1_73_0/libs/locale/src/win32目录中所做的修改如下:

api.h

// detecting UWP
#include <boost/predef.h>

// ...

    class winlocale{
    public:
        winlocale() :
          lcid(0)
        {
        }

        winlocale(std::string const name)
        {
#if BOOST_PLAT_WINDOWS_RUNTIME
          str.assign(cbegin(name), cend(name));
#endif
          lcid = locale_to_lcid(name);
        }

#if BOOST_PLAT_WINDOWS_RUNTIME
        std::wstring str;
#endif

        unsigned lcid;
        bool is_c() const
        {
          return lcid == 0;
        }
    };

// ...

    inline std::wstring win_map_string_l(unsigned flags,wchar_t const *begin,wchar_t const *end,winlocale const &l)
    {
        std::wstring res;

#if BOOST_PLAT_WINDOWS_RUNTIME
        int len = LCMapStringEx(l.str.c_str(), flags, begin, end - begin, 0, 0,
          /* >=win_vista must set to null*/ 0,
          /*Reserved; must be NULL.*/ 0,
          /*Reserved; must be 0.*/ 0);
        if (len == 0)
          return res;
        std::vector<wchar_t> buf(len + 1);
        int l2 = LCMapStringEx(l.str.c_str(), flags, begin, end - begin, &buf.front(), buf.size(),
          /* >=win_vista must set to null*/ 0,
          /*Reserved; must be NULL.*/ 0,
          /*Reserved; must be 0.*/ 0);
        res.assign(&buf.front(), l2);
#else
        int len = LCMapStringW(l.lcid,flags,begin,end-begin,0,0);
        if(len == 0)
            return res;
        std::vector<wchar_t> buf(len+1);
        int l2 = LCMapStringW(l.lcid,flags,begin,end-begin,&buf.front(),buf.size());
        res.assign(&buf.front(),l2);
#endif

        return res;
    }

// …

    inline std::wstring wcsfmon_l(double value,winlocale const &l)
    {
        std::wostringstream ss;
        ss.imbue(std::locale::classic());

        ss << std::setprecision(std::numeric_limits<double>::digits10+1) << value;
        std::wstring sval = ss.str();
#if BOOST_PLAT_WINDOWS_RUNTIME 
        int len = GetCurrencyFormatEx(l.str.c_str(), 0, sval.c_str(), 0, 0, 0);
        std::vector<wchar_t> buf(len + 1);
        GetCurrencyFormatEx(l.str.c_str(), 0, sval.c_str(), 0, &buf.front(), len);
#else
        int len = GetCurrencyFormatW(l.lcid,0,sval.c_str(),0,0,0);
        std::vector<wchar_t> buf(len+1);
        GetCurrencyFormatW(l.lcid,0,sval.c_str(),0,&buf.front(),len);
#endif
        return &buf.front();
    }

    inline std::wstring wcs_format_date_l(wchar_t const *format,SYSTEMTIME const *tm,winlocale const &l)
    {
#if BOOST_PLAT_WINDOWS_RUNTIME
        int len = GetDateFormatEx(l.str.c_str(), 0, tm, format, 0, 0,
          /*Reserved; must set to NULL.*/ 0);
        std::vector<wchar_t> buf(len + 1);
        GetDateFormatEx(l.str.c_str(), 0, tm, format, &buf.front(), len,
          /*Reserved; must set to NULL.*/ 0);
#else
        int len = GetDateFormatW(l.lcid,0,tm,format,0,0);
        std::vector<wchar_t> buf(len+1);
        GetDateFormatW(l.lcid,0,tm,format,&buf.front(),len);
#endif
        return &buf.front(); 
    }

    inline std::wstring wcs_format_time_l(wchar_t const *format,SYSTEMTIME const *tm,winlocale const &l)
    {
#if BOOST_PLAT_WINDOWS_RUNTIME
        int len = GetTimeFormatEx(l.str.c_str(), 0, tm, format, 0, 0);
        std::vector<wchar_t> buf(len + 1);
        GetTimeFormatEx(l.str.c_str(), 0, tm, format, &buf.front(), len);
#else
        int len = GetTimeFormatW(l.lcid, 0, tm, format, 0, 0);
        std::vector<wchar_t> buf(len + 1);
        GetTimeFormatW(l.lcid, 0, tm, format, &buf.front(), len);
#endif
        return &buf.front(); 
    }

lcid.cpp

BOOL CALLBACK procEx(LPWSTR s, DWORD, LPARAM)
{
  table_type& tbl = real_lcid_table();
  try {
    std::wistringstream ss;
    ss.str(s);
    ss >> std::hex;

    unsigned lcid;
    ss >> lcid; // <----- not sure about this line, but anyway...
    if (ss.fail() || !ss.eof()) {
      return FALSE;
    }

    char iso_639_lang[16];
    char iso_3166_country[16];
    if (GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, iso_639_lang, sizeof(iso_639_lang)) == 0)
      return FALSE;
    std::string lc_name = iso_639_lang;
    if (GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, iso_3166_country, sizeof(iso_3166_country)) != 0) {
      lc_name += "_";
      lc_name += iso_3166_country;
    }
    table_type::iterator p = tbl.find(lc_name);
    if (p != tbl.end()) {
      if (p->second > lcid)
        p->second = lcid;
    }
    else {
      tbl[lc_name] = lcid;
    }
  }
  catch (...) {
    tbl.clear();
    return FALSE;
  }
  return TRUE;
}

table_type  const &get_ready_lcid_table()
{
    if(table)
        return *table;
    else {
        boost::unique_lock<boost::mutex> lock(lcid_table_mutex());
        if(table)
            return *table;
#if BOOST_PLAT_WINDOWS_RUNTIME
        EnumSystemLocalesEx(procEx, LCID_INSTALLED,
          /*callback arg*/ 0, /*reserved*/ 0);
#else
        EnumSystemLocalesA(proc, LCID_INSTALLED);
#endif
        table = &real_lcid_table();
        return *table;
    }
}

更新

我发现,这个问题实际上是由包含<boost/predef.h>api.h中引起的,我在适当的时候用它来定义BOOST_PLAT_WINDOWS_RUNTIME宏。但是,我仍然不知道如何处理这种情况。有人可以指点我的地方吗?谢谢你。

4

0 回答 0