C++中特定于线程的区域设置操作

Thread specific locale manipulation in C++

本文关键字:区域 设置 操作 线程 于线程 C++      更新时间:2023-10-16

是否有任何标准的方法可以跨平台按线程设置区域设置?我看到xlocale提供了uselocale,但在Windows中不支持它。窗口中有"_configthreadlocale(_ENABLE_PER_THREAD_LOCALE(;",之后setlocale按每个线程工作。我的问题是,是否有一个库以独立于平台的方式提供这些特定于区域设置的操作???或者其他方式?

谢谢,Gokul。

我也遇到过同样的问题,我最终为它写了一些小的交叉兼容性代码。我试图尽可能地遵循规范,但它确实有一些局限性。

在这段代码中,newlocale不允许您指定基本区域设置,也不能混合使用类别掩码。但对于不同地区之间的一些基本切换来说,这就足够了。

// Locale Cross-Compatibility
#ifdef _WIN32
#define locale_t         _locale_t
#define freelocale       _free_locale
#define LC_GLOBAL_LOCALE ((locale_t)-1)
#define LC_ALL_MASK      LC_ALL
#define LC_COLLATE_MASK  LC_COLLATE
#define LC_CTYPE_MASK    LC_CTYPE
#define LC_MONETARY_MASK LC_MONETARY
#define LC_NUMERIC_MASK  LC_NUMERIC
#define LC_TIME_MASK     LC_TIME
// Base locale is ignored and mixing of masks is not supported
#define newlocale(mask, locale, base) _create_locale(mask, locale)
locale_t uselocale(locale_t new_locale)
{
    // Retrieve the current per thread locale setting
    bool bIsPerThread = (_configthreadlocale(0) == _ENABLE_PER_THREAD_LOCALE);
    // Retrieve the current thread-specific locale
    locale_t old_locale = bIsPerThread ? _get_current_locale() : LC_GLOBAL_LOCALE;
    if(new_locale == LC_GLOBAL_LOCALE)
    {
        // Restore the global locale
        _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
    }
    else if(new_locale != NULL)
    {
        // Configure the thread to set the locale only for this thread
        _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
        // Set all locale categories
        for(int i = LC_MIN; i <= LC_MAX; i++)
            setlocale(i, new_locale->locinfo->lc_category[i].locale);
    }
    return old_locale;
}
#endif

把这些代码放在你的项目中,你就可以在任何这样的平台上切换每个线程的区域设置:

#include <locale.h>
#ifdef __APPLE__
#include <xlocale.h>
#endif
// Apply a new locale to this thread
locale_t locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
locale_t old_locale = uselocale(locale);
// Print out some text
printf("Always use dot-decimal notation: %f", 1.5);
// Restore the global locale
uselocale(old_locale);
freelocale(locale);
Boost::Locale提供了一个基于iconv库的跨平台语言环境接口。如果您希望C标准库函数在设置区域设置后立即正常工作,那么它可能不是理想的接口。相反,您将手动将区域设置作为对象进行管理,并显式使用它们。您显式地生成区域设置,并使用它们来创建比较器和其他任何您需要的特定于区域设置的东西。

一方面,这意味着您以前编写的任何依赖于特定语言环境的代码都必须重写。另一方面,隐藏在引擎盖下的gotcha要少得多,因为你要明确地处理在哪里使用什么语言/编码。