FME Version
Introduction
This article provides a guide for upgrading C++ FME Plug-ins to the latest version of the FME API. In FME 2022.0 release, FME changed the default string encoding from the operating system locale encoding (e.g. Windows-1252) to UTF-8 on supported Windows 10 and later operating systems.
Benefits of migrating to the new FME API include:
- Improved support for international characters in feature type names, attribute names, trait names, coordinate system names, datasets, or other file paths
- Increased workspace portability between all supported operating systems and locales
- Improved performance due to reduced transcoding operations
FAQ Overview
- How is the Windows SDK version different from the Windows version?
- Why require a minimum Windows SDK version of 10.0.17134.0?
- What are the implications of setting a process locale?
- What is the difference between Shared and Independent C++ runtimes?
- What is the definition of the new FMEPluginCapabilities DLL entry point?
- What does setPluginLocale() (2022.0) and setPluginLocaleW() (2023.0) do?
- How to verify the locale is set correctly in a plug-in for FME 2022.0?
All existing plug-ins must be upgraded to work with FME 2022.0 or newer. Upgrading to use the new FME 2022.0 API version requires recompilation of the plug-in, making a few entry point changes, and potentially adjusting locale usage to work correctly with the UTF-8 or operating system encodings used by FME.
FAQ
Note: whenever setlocale() is mentioned the same applies to _wsetlocale() as the latter is a Windows specialization that supports wide (wchar_t) strings in FME 2023.0+.
How is the Windows SDK version different from the Windows version?
The Windows SDK version is the target that the plug-in will be compiled against and is defined per plug-in in the Visual Studio project settings and must be at least 10.0.17134.0.
The Windows SDK version is distinct from the Windows operating system version, which can be seen in System Information on Windows. Note: Windows 10 must be at least version 1903 or Windows Server 2019 must be at least version 1809 and build 17763.1339 to support a UTF-8 encoding via setlocale() and _wsetlocale().
Why require a minimum Windows SDK version of 10.0.17134.0?
Microsoft has added support for setting C Runtime locale to UTF-8 in Windows 10 build 17134 - the April 2018 Update, which also coincides with the minimum Windows 10 version required for FME UTF-8 operation.
What are the implications of setting a process locale?
Setting the process locale influences the execution of all locale-sensitive C library functions. For further information on setlocale() and _wsetlocale(), please refer to the C++ documentation and Microsoft documentation, respectively.
For example, if the process locale was set to the UTF-8 encoding, the following is valid on any Windows version that supports the UTF-8 encoding:
// This file name will work on any locale! std::string filename(u8"サンプルファイル.txt"); std::fstream exampleFile; exampleFile.open(filename);
In contrast, if the locale encoding were set to Windows-1252, only characters that are valid on that code page would be allowed.
What is the difference between Shared and Independent C++ runtimes?
The Runtime Library setting can be found in Visual Studio project settings
Property Pages → Configuration Properties → C/C++ → Code Generation → Runtime Library
Shared Runtime - Multi-Threaded DLL (/MD in Visual Studio)
- Resources and various settings, including process locale settings are shared between all other /MD compilation units within the same process
- E.g. Setting the locale in a shared runtime DLL sets the locale for all other compilation units loaded from all other DLLs compiled with a shared runtime in the same process.
- This includes any dependent DLLs loaded by a plug-in or any dependent DLL
Independent Runtime - Multi-Threaded (/MT in Visual Studio)
- Independent resources and settings from other compilation units
- E.g. Setting the locale in an independent runtime DLL only affects compilation units in that DLL and in any libraries statically linked into the DLL
What is the definition of the new FMEPluginCapabilities DLL entry point?
For FME plug-ins for versions 2021.1+, FME introduced a new DLL entry point which is a centralized way for a plug-in to advertise and customize various capabilities. FMEPluginCapabilities is located in
<fme install directory>/pluginbuilder/cpp/fmeplugincapabilities.h.
Below is the recommended default implementation of the new entry point for all plug-ins:
// located in 'pluginbuilder/cpp' see file comments for more detail #include <fmeplugincapabilities.h> // Return current plugin's capabilities FME_DLLEXPORT_C const FMEPluginCapabilities* FME_getPluginCapabilities() { static const FMEPluginCapabilities capabilities; return &capabilities; }
What does setPluginLocale() (2022.0) and setPluginLocaleW() (2023.0) do?
In FME 2023.0 setPluginLocale() has been superseded by setPluginLocaleW() in order to take advantage of the wide string _wsetlocale() variant. If migrating to 2023.0, please use setPluginLocaleW() instead of setPluginLocale().
The setPluginLocale() method on the FME Plug-in SDK allows FME to set up the default string encoding when communicating with a plug-in.
As of FME 2022.0, the default process locale and encoding are UTF-8. When using the default implementation of FME_getPluginCapabilities, the following can be expected from all API calls:
- All const char * and IFMEStrings without an accompanying encoding parameter will be UTF-8 encoded
- All strings returned via const char* and IFMEString by the plug-in are expected to be UTF-8 encoded
- File paths containing international characters are now supported
If a plug-in is compiled with a C++ Shared Runtime (/MD):
- Whenever setlocale() is called from any shared runtime DLL, the setting affects all DLLs using the same shared runtime, including every compilation unit in the DLL.
- As of the FME 2022.0 release, FME sets the locale for all shared runtime DLLs to UTF-8. Plug-in authors should avoid calling setlocale() anywhere within the plug-in if using the C++ shared runtime.
- If calling setlocale() is unavoidable, or the plug-in requires a specific locale please contact Safe Software support to discuss potential options for resolving this issue.
If a plug-in is compiled with an C++ Independent Runtime (/MT):
- setlocale() settings only affect methods within the calling DLL. Therefore, it is possible for FME and a plug-in to have different locales, provided the encoding of strings passed to the FME plug-in API is in the encoding expected by FME.
How to verify the locale is set correctly in a plug-in for FME 2022.0?
FMEPluginCapabilities is available starting from FME 2022.0 betas for development and testing.
A mixed encoding string containing Japanese, English, Russian and Thai characters can be a good test to ensure correct UTF-8 operation:
だめもじ_mixed_тест_ทดสอบ
The example string can be used by any string in FME, including feature type names, attribute names, trait names, coordinate system names, or as part of a file path.
In FME 2022.0 and beyond, these non-ASCII characters should be correctly preserved in the FME application GUIs, logfile, and data files as supported by specific formats.
If the test string appears garbled or contains replacement characters such as question marks, this may be an indication that encodings are not being set or interpreted correctly.
Comments
0 comments
Please sign in to leave a comment.