Reputation: 860
I'm working on a C++/WinRT project and would like to use Boost (1.73.0) Locale in it. Inspired by a Microsoft blog post I have replaced calls to unsupported WinApi functions in the library sources and compiled with windows-api=store
. I managed to build all intended library variants (arm / x64, debug / release) and went on to build the UWP app. That is the point where I am stuck right now. The build fails to link with the following output:
vccorlibd.lib(init.obj) : error LNK2038: mismatch detected for 'vccorlib_lib_should_be_specified_before_msvcrt_lib_to_linker': value '1' doesn't match value '0' in MSVCRTD.lib(app_appinit.obj)
vccorlibd.lib(init.obj) : error LNK2005: __crtWinrtInitType already defined in MSVCRTD.lib(app_appinit.obj)
The line triggering the failure:
const auto text = boost::locale::conv::to_utf<char>("xxx", "yyy");
My setup is Visual Studio 17 & 19, SDK 10.0.19041.0. I have tried this solution proposed to a similar question but to no avail. The modifications I made in the boost_1_73_0/libs/locale/src/win32 directory follow:
// 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();
}
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;
}
}
I found out, that the problem is actually caused by inclusion of <boost/predef.h>
in the api.h, which I use to define the BOOST_PLAT_WINDOWS_RUNTIME
macro when appropriate. I still don't know how to handle this situation however. Can anybody point me somewhere? Thank you.
Upvotes: 0
Views: 231