1--- 2layout: default 3title: Plug-ins 4nav_order: 4 5parent: ICU Data 6--- 7<!-- 8© 2020 and later: Unicode, Inc. and others. 9License & terms of use: http://www.unicode.org/copyright.html 10--> 11 12# Plug-ins 13{: .no_toc } 14 15## Contents 16{: .no_toc .text-delta } 17 181. TOC 19{:toc} 20 21--- 22 23## Overview 24 25This page documents the ICU4C DLL Plug-in capability. 26This feature is a Technology Preview which first appeared in ICU4C version 274.3.4. It may be altered or removed in subsequent releases, and feedback is 28appreciated. 29 30## Off by default 31 32As per ticket [ICU-11763](https://unicode-org.atlassian.net/browse/ICU-11763), the plugin 33mechanism discussed here is disabled by default as of ICU 56. Use 34**--enable-plugins** and/or define **UCONFIG_ENABLE_PLUGINS=1** to enable the 35mechanism. 36 37## Background 38 39ICU4C has functionality for registering services, setting 40mutex/allocation handlers, etc. But they must be installed 'before any 41ICU services are used' 42The ICU plugin mechanism allows small code modules, called plugins, to be loaded 43automatically when ICU starts. 44 45## How it works 46 47At u_init time, ICU will read from a list of DLLs and entrypoints, and 48attempt to load plugins found in the list. plugins are called and can 49perform any ICU related function, such as registering or unregistering 50service objects. At u_cleanup time, plugins have the opportunity to 51uninstall themselves before they are removed from memory and unloaded. 52 53## Plugin API 54 55The current plugin API is documented as 56[icuplug.h](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/icuplug_8h.html) 57Some sample plugins are available at: 58[testplug.c](https://github.com/unicode-org/icu/blob/master/icu4c/source/tools/icuinfo/testplug.c) 59Here is a simple, trivial plugin: 60 61```c 62U_CAPI 63UPlugTokenReturn U_EXPORT2 myPlugin (UPlugData *data, UPlugReason reason, UErrorCode *status) { 64 if(reason==UPLUG_REASON_QUERY) { 65 uplug_setPlugName(data, "Simple Plugin"); /* optional */ 66 uplug_setPlugLevel(data, UPLUG_LEVEL_HIGH); /* Mandatory */ 67 } else if(reason==UPLUG_REASON_LOAD) { 68 /* ... load ... */ 69 /* Set up some ICU things here. */ 70 } else if(reason==UPLUG_REASON_UNLOAD) { 71 /* ... unload ... */ 72 } 73 return UPLUG_TOKEN; /* Mandatory. */ 74} 75``` 76 77The `UPlugData*` is an opaque pointer to the plugin-specific data, 78and is used in all other API calls. 79 80The API contract is: 81 821. the plugin MUST always return UPLUG_TOKEN as a return value- to 83indicate that it is a valid plugin. 84 852. when the 'reason' parameter is set to UPLUG_REASON_QUERY, the 86plugin MUST call `uplug_setPlugLevel()` to indicate whether it is a high 87level or low level plugin. 88 893. when the 'reason' parameter is UPLUG_REASON_QUERY, the plugin 90SHOULD call `uplug_setPlugName` to indicate a human readable plugin name. 91 92## Configuration 93 94You can see a sample configuration file here: 95[icuplugins_windows_sample.txt](https://github.com/unicode-org/icu/blob/master/icu4c/source/tools/icuinfo/icuplugins_windows_sample.txt) 96At ICU startup time, the environment variable "ICU_PLUGINS" will be 97queried for a directory name. If it is not set, the #define 98`DEFAULT_ICU_PLUGINS` will be checked for a default value. 99`DEFAULT_ICU_PLUGINS` will be set, on autoconf'ed and installed ICU 100versions, to "$(prefix)/lib/icu" if not set otherwise by the build 101environment. 102Within the above-named directory, the file "icuplugins##.txt" will be 103opened, if present, where _##_ is the major+minor number of the currently 104running ICU (such as, 44 for ICU 4.4). 105So, for example, by default, ICU 4.4 would attempt to open 106`$(prefix)/lib/icu/icuplugins44.txt` 107The configuration file has the following format: 1081. Hash (#) begins a comment line 1092. Non-comment lines have two or three components: 110 > `LIBRARYNAME ENTRYPOINT [ CONFIGURATION .. ]` 1113. Tabs or spaces separate the three items. 1124. _LIBRARYNAME_ is the name of a shared library, either a short name if 113it is on the loader path, or a full pathname. 1145. _ENTRYPOINT_ is the short (undecorated) symbol name of the plugin's 115entrypoint, as above. 1166. _CONFIGURATION_ is the entire rest of the line. It's passed as-is to 117the plugin. 118 119An example configuration file is, in its entirety: 120 121``` 122# this is icuplugins44.txt 123testplug.dll myPlugin hello=world 124``` 125 126The DLL testplug.dll is opened, and searched for the entrypoint 127"myPlugin", which must meet the API contract above. 128The string "hello=world" is passed to the plugin verbatim. 129 130## Load Order 131 132Plugins are categorized as "high" or "low" level. Low level are those 133which must be run BEFORE high level plugins, and before any operations 134which cause ICU to be 'initialized'. If a plugin is low level but 135causes ICU to allocate memory or become initialized, that plugin is said 136to cause a 'level change'. 137At load time, ICU first queries all plugins to determine their level, 138then loads all 'low' plugins first, and then loads all 'high' plugins. 139Plugins are otherwise loaded in the order listed in the configuration file. 140 141## User interface and troubleshooting 142 143The new command line utility, `icuinfo`, will not only print out ICU 144version information, but will also give information on the load status 145of plugins, with the "-L" option. It will list all loaded or 146possibly-loaded plugins, give their level, and list any errors 147encountered which prevented them from loading. Thus, the end user can 148validate their plugin configuration file to determine if plugins are 149missing, unloadable, or loaded in the wrong order. 150For example the following run shows that the plugin named 151"myPluginFailQuery" did not call `uplug_setPlugLevel()` and thus failed to 152load. 153 154``` 155$ icuinfo -v -L 156Compiled against ICU 4.3.4, currently running ICU 4.3.4 157ICUDATA is icudt43l 158plugin file is: /lib/plugins/icuplugins43.txt 159Plugins: 160# Level Name 161Library:Symbol 162config| (configuration string) 163>>> Error | Explanation 164----------------------------------- 165 166#1 HIGH Just a Test High-Level Plugin 167plugin| /lib/plugins/libplugin.dylib:myPlugin 168config| x=4 169 170#2 HIGH High Plugin 171plugin| /lib/plugins/libplugin.dylib:myPluginHigh 172config| x=4 173 174#3 INVALID this plugin did not call uplug_setPlugName() 175plugin| /lib/plugins/libplugin.dylib:myPluginFailQuery 176config| uery 177\\\ status| U_PLUGIN_DIDNT_SET_LEVEL 178/// Error: This plugin did not call uplug_setPlugLevel during QUERY. 179 180#4 LOW Low Plugin 181plugin| /lib/plugins/libplugin.dylib:myPluginLow 182config| x=4 183Default locale is en_US 184Default converter is UTF-8. 185``` 186