<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Blosc Home Page  (Posts about blosc2 plugin dynamic)</title><link>https://blosc.org/</link><description></description><atom:link href="https://blosc.org/categories/blosc2-plugin-dynamic.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2026 &lt;a href="mailto:blosc@blosc.org"&gt;The Blosc Developers&lt;/a&gt; </copyright><lastBuildDate>Sun, 19 Jul 2026 11:09:13 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Dynamic plugins in C-Blosc2</title><link>https://blosc.org/posts/dynamic-plugins/</link><dc:creator>Marta Iborra, Francesc Alted</dc:creator><description>&lt;p&gt;&lt;strong&gt;Updated: 2023-08-03&lt;/strong&gt;
Added a new example of a dynamic filter for Python. Also, we have improved the content so that it can work more as a tutorial on how to make dynamic plugins for Blosc2. Finally, there is support now for dynamic plugins on Windows and MacOS/ARM64. Enjoy!&lt;/p&gt;
&lt;p&gt;The Blosc Development Team is excited to announce that the latest version of &lt;a class="reference external" href="https://github.com/Blosc/c-blosc2"&gt;C-Blosc2&lt;/a&gt; and &lt;a class="reference external" href="https://github.com/Blosc/python-blosc2"&gt;Python-Blosc2&lt;/a&gt;
include a great new feature: the ability to dynamically load plugins, such as codecs and filters. This means that these codecs
or filters will only be loaded at runtime when they are needed. These C libraries will be easily distributed inside Python
wheels and be used from both C and Python code without problems.  Keep reading for a gentle introduction to this new feature.&lt;/p&gt;
&lt;section id="creating-a-dynamically-loaded-filter"&gt;
&lt;h2&gt;Creating a dynamically loaded filter&lt;/h2&gt;
&lt;p&gt;To learn how to create dynamic plugins, we'll use an &lt;a class="reference external" href="https://github.com/Blosc/blosc2_plugin_example"&gt;already created example&lt;/a&gt;.  Suppose you have a filter that you want Blosc2 to load dynamically only when it is used. In this case, you need to create a Python package to build a wheel and install it as a separate library. You can follow the structure used in &lt;a class="reference external" href="https://github.com/Blosc/blosc2_plugin_example"&gt;blosc2_plugin_example&lt;/a&gt; to do this:&lt;/p&gt;
&lt;pre class="literal-block"&gt;├── CMakeLists.txt
├── README.md
├── blosc2_plugin_name
│   └── __init__.py
├── examples
│   ├── array_roundtrip.py
│   ├── schunk_roundtrip.py
│   └── test_plugin.c
├── pyproject.toml
├── requirements-build.txt
├── setup.py
└── src
    ├── CMakeLists.txt
    ├── urfilters.c
    └── urfilters.h&lt;/pre&gt;
&lt;p&gt;Note that the project name has to be &lt;cite&gt;blosc2_&lt;/cite&gt; followed by the plugin name (&lt;cite&gt;plugin_example&lt;/cite&gt; in this case). The corresponding functions will be defined in the &lt;cite&gt;src&lt;/cite&gt; folder, in our case in &lt;cite&gt;urfilters.c&lt;/cite&gt;, following the same format as functions for user-defined filters (see &lt;a class="reference external" href="https://github.com/Blosc/c-blosc2/blob/main/plugins/README.md"&gt;https://github.com/Blosc/c-blosc2/blob/main/plugins/README.md&lt;/a&gt; for more information).  Here it is the sample code:&lt;/p&gt;
&lt;pre class="literal-block"&gt;int blosc2_plugin_example_forward(const uint8_t* src, uint8_t* dest,
                                  int32_t size, uint8_t meta,
                                  blosc2_cparams *cparams, uint8_t id) {
  blosc2_schunk *schunk = cparams-&amp;gt;schunk;

  for (int i = 0; i &amp;lt; size / schunk-&amp;gt;typesize; ++i) {
    switch (schunk-&amp;gt;typesize) {
      case 8:
        ((int64_t *) dest)[i] = ((int64_t *) src)[i] + 1;
        break;
      default:
        BLOSC_TRACE_ERROR("Item size %d not supported", schunk-&amp;gt;typesize);
        return BLOSC2_ERROR_FAILURE;
    }
  }
  return BLOSC2_ERROR_SUCCESS;
}


int blosc2_plugin_example_backward(const uint8_t* src, uint8_t* dest, int32_t size,
                                   uint8_t meta, blosc2_dparams *dparams, uint8_t id) {
  blosc2_schunk *schunk = dparams-&amp;gt;schunk;

  for (int i = 0; i &amp;lt; size / schunk-&amp;gt;typesize; ++i) {
    switch (schunk-&amp;gt;typesize) {
      case 8:
        ((int64_t *) dest)[i] = ((int64_t *) src)[i] - 1;
        break;
      default:
        BLOSC_TRACE_ERROR("Item size %d not supported", schunk-&amp;gt;typesize);
        return BLOSC2_ERROR_FAILURE;
    }
  }
  return BLOSC2_ERROR_SUCCESS;
}&lt;/pre&gt;
&lt;p&gt;In addition to these functions, we need to create a &lt;cite&gt;filter_info&lt;/cite&gt; (or &lt;cite&gt;codec_info&lt;/cite&gt; or &lt;cite&gt;tune_info&lt;/cite&gt; in each case) named &lt;cite&gt;info&lt;/cite&gt;. This variable will contain the names of the &lt;cite&gt;forward&lt;/cite&gt; and &lt;cite&gt;backward&lt;/cite&gt; functions. In our case, we will have:&lt;/p&gt;
&lt;pre class="literal-block"&gt;filter_info info  = {"blosc2_plugin_example_forward", "blosc2_plugin_example_backward"};&lt;/pre&gt;
&lt;p&gt;To find the functions, the variable must always be named &lt;cite&gt;info&lt;/cite&gt;. Furthermore, the symbols &lt;cite&gt;info&lt;/cite&gt; and the functions
&lt;cite&gt;forward&lt;/cite&gt; and &lt;cite&gt;backward&lt;/cite&gt; must be exported in order for Windows to find them. You can see all the details for doing that in
the &lt;a class="reference external" href="https://github.com/Blosc/blosc2_plugin_example/blob/cbbcab59a6abf5d1a0767604b1987edd34695fe8/src/urfilters.h#L46-L50"&gt;blosc2_plugin_example repository&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="creating-and-installing-the-wheel"&gt;
&lt;h2&gt;Creating and installing the wheel&lt;/h2&gt;
&lt;p&gt;Once the project is done, you can create a wheel and install it locally:&lt;/p&gt;
&lt;pre class="literal-block"&gt;python setup.py bdist_wheel
pip install dist/*.whl&lt;/pre&gt;
&lt;p&gt;This wheel can be uploaded to PyPI so that anybody can use it. Once tested and stable enough, you can &lt;a class="reference external" href="https://github.com/Blosc/c-blosc2/blob/main/plugins/README.md"&gt;request the Blosc Team to register it globally&lt;/a&gt;. This way, an ID for the filter or codec will be booked so that the data will always be able to be encoded/decoded by the same code, ensuring portability.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="registering-the-plugin-in-c-blosc2"&gt;
&lt;h2&gt;Registering the plugin in C-Blosc2&lt;/h2&gt;
&lt;p&gt;After installation, and prior to use it, you must register it in C-Blosc2. This step is necessary only if the filter is not already registered globally by C-Blosc2, which is likely if you are testing it or you are not ready to share it with other users. To register it, follow the same process as registering a &lt;a class="reference external" href="https://www.blosc.org/posts/registering-plugins/"&gt;user-defined plugin&lt;/a&gt;, but leave the function pointers as NULL:&lt;/p&gt;
&lt;pre class="literal-block"&gt;blosc2_filter plugin_example;
plugin_example.id = 250;
plugin_example.name = "plugin_example";
plugin_example.version = 1;
plugin_example.forward = NULL;
plugin_example.backward = NULL;
blosc2_register_filter(&amp;amp;plugin_example);&lt;/pre&gt;
&lt;p&gt;When the filter is used for the first time, C-Blosc2 will automatically fill in the function pointers.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="registering-the-plugin-in-python-blosc2"&gt;
&lt;h2&gt;Registering the plugin in Python-Blosc2&lt;/h2&gt;
&lt;p&gt;The same applies for Python-Blosc2. You can register the filter as follows:&lt;/p&gt;
&lt;pre class="literal-block"&gt;import blosc2
blosc2.register_filter(250, None, None, "plugin_example")&lt;/pre&gt;
&lt;/section&gt;
&lt;section id="using-the-plugin-in-c-blosc2"&gt;
&lt;h2&gt;Using the plugin in C-Blosc2&lt;/h2&gt;
&lt;p&gt;To use the plugin, simply set the filter ID in the filters pipeline, as you would do with user-defined filters:&lt;/p&gt;
&lt;pre class="literal-block"&gt;blosc2_cparams cparams = BLOSC2_CPARAMS_DEFAULTS;
cparams.filters[4] = 250;
cparams.filters_meta[4] = 0;

blosc2_dparams dparams = BLOSC2_DPARAMS_DEFAULTS;

blosc2_schunk* schunk;

/* Create a super-chunk container */
cparams.typesize = sizeof(int32_t);
blosc2_storage storage = {.cparams=&amp;amp;cparams, .dparams=&amp;amp;dparams};
schunk = blosc2_schunk_new(&amp;amp;storage);&lt;/pre&gt;
&lt;p&gt;To see a full usage example, refer to &lt;a class="reference external" href="https://github.com/Blosc/blosc2_plugin_example/blob/main/examples/test_plugin.c"&gt;https://github.com/Blosc/blosc2_plugin_example/blob/main/examples/test_plugin.c&lt;/a&gt;. Keep in mind that the executable using the plugin must be launched from the same virtual environment where the plugin wheel was installed. When compressing or decompressing, C-Blosc2 will dynamically load the library and call its functions automatically (as depicted below).&lt;/p&gt;
&lt;img alt="Dynamically loading filter" src="https://blosc.org/images/dynamic-plugins/dynamic-plugin.png" style="width: 100%;"&gt;
&lt;p&gt;Once you are satisfied with your plugin, you may choose to request the Blosc Development Team to register it as a global plugin. The only difference (aside from its ID number) is that users won't need to register it locally anymore. Also, a dynamic plugin will not be loaded until it is explicitly requested by any compression or decompression function, saving resources.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="using-the-plugin-in-python-blosc2"&gt;
&lt;h2&gt;Using the plugin in Python-Blosc2&lt;/h2&gt;
&lt;p&gt;As in C-Blosc2, just set the filter ID in the filters pipeline, as you would do with user-defined filters:&lt;/p&gt;
&lt;pre class="literal-block"&gt;shape = [100, 100]
size = int(np.prod(shape))
nparray = np.arange(size, dtype=np.int32).reshape(shape)
blosc2_array = blosc2.asarray(nparray, cparams={"filters": [250]})&lt;/pre&gt;
&lt;p&gt;To see a full usage example, refer to &lt;a class="reference external" href="https://github.com/Blosc/blosc2_plugin_example/blob/main/examples/array_roundtrip.py"&gt;https://github.com/Blosc/blosc2_plugin_example/blob/main/examples/array_roundtrip.py&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="conclusions"&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;C-Blosc2's ability to support dynamically loaded plugins allows the library to grow in features without increasing the size and complexity of the library itself. For more information about user-defined plugins, refer to this &lt;a class="reference external" href="https://www.blosc.org/posts/registering-plugins/"&gt;blog entry&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We appreciate your interest in our project! If you find our work useful and valuable, we would be grateful if you could support us by &lt;a class="reference external" href="https://www.blosc.org/pages/donate/"&gt;making a donation&lt;/a&gt;. Your contribution will help us continue to develop and improve Blosc packages, making them more accessible and useful for everyone.  Our team is committed to creating high-quality and efficient software, and your support will help us to achieve this goal.&lt;/p&gt;
&lt;/section&gt;</description><category>blosc2 plugin dynamic</category><guid>https://blosc.org/posts/dynamic-plugins/</guid><pubDate>Wed, 10 May 2023 08:32:20 GMT</pubDate></item></channel></rss>