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):| Platform | File extension | Example path |
|---|---|---|
| Linux / BSD | .so | ~/.config/mpv/scripts/myplugin.so |
| Windows | .dll | %APPDATA%\mpv\scripts\myplugin.dll |
Required export
Every C plugin must export exactly one function: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
| Return value | Meaning |
|---|---|
0 | Plugin loaded successfully |
-1 | Error; mpv prints a loading failure message |
Event loop pattern
Becausempv_open_cplugin must not return, the typical plugin body is an event loop using mpv_wait_event():
Interacting with the player
Withinmpv_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 againstlibmpv.
- Linux / BSD
- Windows
-rdynamic (which mpv enables when building).Minimal complete example
Linkage rules
Why not link against libmpv?
Why not link against libmpv?
C plugins are loaded into the mpv process at runtime. Their symbols are resolved against the host binary (mpv itself or any application that embeds libmpv). Linking the plugin against
libmpv.so would create a second, conflicting copy of the mpv core inside the same process.How does MPV_CPLUGIN_DYNAMIC_SYM work?
How does MPV_CPLUGIN_DYNAMIC_SYM work?
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.Can a plugin use other mpv headers?
Can a plugin use other mpv headers?
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.