Skip to main content
C plugins let you extend mpv with native code. They use the libmpv API but are loaded directly into the mpv process — you do not link against libmpv.so or libmpv.dll. Instead, your plugin uses symbols exported from the mpv host binary.
C plugins are enabled by default on Linux/BSD when the compiler supports -rdynamic, and are always enabled on Windows.

Plugin location

mpv discovers C plugins automatically from the scripts directory in its config directory (the same location as Lua scripts): You can also load a plugin explicitly regardless of location:

Required export

Every C plugin must export exactly one function:
mpv calls this function when the plugin is loaded. The function receives an mpv_handle that belongs to the plugin — it was created internally with the equivalent of mpv_create_client(). The function must not return for as long as the plugin is loaded. It runs in its own dedicated thread. When the function returns, the handle is destroyed.

Return values

Any other return value is reserved and triggers undefined behavior.

Event loop pattern

Because mpv_open_cplugin must not return, the typical plugin body is an event loop using mpv_wait_event():
Do not call mpv_destroy() or mpv_terminate_destroy() on the handle passed to mpv_open_cplugin. mpv owns and manages that handle’s lifetime.

Interacting with the player

Within mpv_open_cplugin, you have full access to the libmpv API through the provided handle:

Compile instructions

Compile the plugin as a shared library. Do not link against libmpv.
The plugin resolves mpv symbols from the host binary at runtime via -rdynamic (which mpv enables when building).

Minimal complete example

Linkage rules

When this macro is defined, the mpv/client.h header declares a function pointer (e.g. pfn_mpv_wait_event) for every exported function, then #defines the original name to that pointer. mpv initializes all pointers before calling mpv_open_cplugin, so your code uses the pointers transparently. The pointers are decorated with __declspec(selectany) so multiple translation units do not cause linker errors.
Yes. render.h, render_gl.h, and stream_cb.h all support MPV_CPLUGIN_DYNAMIC_SYM and can be used from a C plugin. Include them after defining the macro.

Further examples

The mpv-examples repository contains additional C plugin examples covering hooks, IPC patterns, and property observation.