我正在开发一个 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
宏。但是,我仍然不知道如何处理这种情况。有人可以指点我的地方吗?谢谢你。