summaryrefslogtreecommitdiffstats
path: root/libmpv/client.h
diff options
context:
space:
mode:
authorKacper Michajłow <kasper93@gmail.com>2023-08-17 16:19:26 +0200
committerDudemanguy <random342@airmail.cc>2023-09-20 02:16:45 +0000
commiteab3842d8bb5ff5465e075fc42d171ac3757903d (patch)
tree17be06e09ab5abdd4185df734ec9595393e268cd /libmpv/client.h
parent4435b1a0d5ac620eda3b18689dff3cb46fd2a732 (diff)
downloadmpv-eab3842d8bb5ff5465e075fc42d171ac3757903d.tar.bz2
mpv-eab3842d8bb5ff5465e075fc42d171ac3757903d.tar.xz
cplugin: allow loading mpv_* symbols dynamically
Defining MPV_CPLUGIN_DYNAMIC_SYM during plugin compilation will replace mpv_* functions with function pointers. Those pointer will be initialized when loading the plugin. It is recommended to use this symbol table when targeting Windows. The loader does not have notion of global symbols. Loading cplugin into mpv process will not allow this plugin to call any of the symbols that may be available in other modules. Instead cplugin has to link explicitly to specific PE binary, libmpv-2.dll/mpv.exe or any other binary that may have linked mpv statically. This limits portability of cplugin as it would need to be compiled separately for each of target PE binary that includes mpv's symbols. Which in practice is unrealictis, as we want one cplugin to be loaded without those restrictions. Instead of linking to any PE binary, we create function pointer for all mpv's exported symbols. For convinience names of entrypoints are redefined to those pointer so no changes are required in cplugin source code, except defining MPV_CPLUGIN_DYNAMIC_SYM. Those function pointer are exported to make them available for mpv to init with correct values during runtime, before calling `mpv_open_cplugin`. Note that those pointer are decorated with `selectany` attribute, so no need to worry about multiple definitions, linker will keep only single instance. This fixes cplugin usability on Windows. Without any API changes, only recompilation with -DMPV_CPLUGIN_DYNAMIC_SYM is needed.
Diffstat (limited to 'libmpv/client.h')
-rw-r--r--libmpv/client.h130
1 files changed, 130 insertions, 0 deletions
diff --git a/libmpv/client.h b/libmpv/client.h
index f9c4420063..4199744ba7 100644
--- a/libmpv/client.h
+++ b/libmpv/client.h
@@ -28,10 +28,19 @@
#ifdef _WIN32
#define MPV_EXPORT __declspec(dllexport)
+#define MPV_SELECTANY __declspec(selectany)
#elif defined(__GNUC__) || defined(__clang__)
#define MPV_EXPORT __attribute__((visibility("default")))
+#define MPV_SELECTANY
#else
#define MPV_EXPORT
+#define MPV_SELECTANY
+#endif
+
+#ifdef __cpp_decltype
+#define MPV_DECLTYPE decltype
+#else
+#define MPV_DECLTYPE __typeof__
#endif
#ifdef __cplusplus
@@ -1888,6 +1897,127 @@ MPV_EXPORT int mpv_get_wakeup_pipe(mpv_handle *ctx);
#endif
+/**
+ * Defining MPV_CPLUGIN_DYNAMIC_SYM during plugin compilation will replace mpv_*
+ * functions with function pointers. Those pointer will be initialized when
+ * loading the plugin.
+ *
+ * It is recommended to use this symbol table when targeting Windows. The loader
+ * does not have notion of global symbols. Loading cplugin into mpv process will
+ * not allow this plugin to call any of the symbols that may be available in
+ * other modules. Instead cplugin has to link explicitly to specific PE binary,
+ * libmpv-2.dll/mpv.exe or any other binary that may have linked mpv statically.
+ * This limits portability of cplugin as it would need to be compiled separately
+ * for each of target PE binary that includes mpv's symbols. Which in practice
+ * is unrealistic, as we want one cplugin to be loaded without those restrictions.
+ *
+ * Instead of linking to any PE binary, we create function pointers for all mpv's
+ * exported symbols. For convenience names of entrypoints are redefined to those
+ * pointer, so no changes are required in cplugin source code, except of defining
+ * MPV_CPLUGIN_DYNAMIC_SYM. Those function pointer are exported to make them
+ * available for mpv to init with correct values during runtime, before calling
+ * `mpv_open_cplugin`.
+ *
+ * Note that those pointers are decorated with `selectany` attribute, so no need
+ * to worry about multiple definitions, linker will keep only single instance.
+ */
+#ifdef MPV_CPLUGIN_DYNAMIC_SYM
+
+#define MPV_DEFINE_SYM_PTR(name) \
+ MPV_SELECTANY MPV_EXPORT \
+ MPV_DECLTYPE(name) *pfn_##name;
+
+MPV_DEFINE_SYM_PTR(mpv_client_api_version)
+#define mpv_client_api_version pfn_mpv_client_api_version
+MPV_DEFINE_SYM_PTR(mpv_error_string)
+#define mpv_error_string pfn_mpv_error_string
+MPV_DEFINE_SYM_PTR(mpv_free)
+#define mpv_free pfn_mpv_free
+MPV_DEFINE_SYM_PTR(mpv_client_name)
+#define mpv_client_name pfn_mpv_client_name
+MPV_DEFINE_SYM_PTR(mpv_client_id)
+#define mpv_client_id pfn_mpv_client_id
+MPV_DEFINE_SYM_PTR(mpv_create)
+#define mpv_create pfn_mpv_create
+MPV_DEFINE_SYM_PTR(mpv_initialize)
+#define mpv_initialize pfn_mpv_initialize
+MPV_DEFINE_SYM_PTR(mpv_destroy)
+#define mpv_destroy pfn_mpv_destroy
+MPV_DEFINE_SYM_PTR(mpv_terminate_destroy)
+#define mpv_terminate_destroy pfn_mpv_terminate_destroy
+MPV_DEFINE_SYM_PTR(mpv_create_client)
+#define mpv_create_client pfn_mpv_create_client
+MPV_DEFINE_SYM_PTR(mpv_create_weak_client)
+#define mpv_create_weak_client pfn_mpv_create_weak_client
+MPV_DEFINE_SYM_PTR(mpv_load_config_file)
+#define mpv_load_config_file pfn_mpv_load_config_file
+MPV_DEFINE_SYM_PTR(mpv_get_time_us)
+#define mpv_get_time_us pfn_mpv_get_time_us
+MPV_DEFINE_SYM_PTR(mpv_free_node_contents)
+#define mpv_free_node_contents pfn_mpv_free_node_contents
+MPV_DEFINE_SYM_PTR(mpv_set_option)
+#define mpv_set_option pfn_mpv_set_option
+MPV_DEFINE_SYM_PTR(mpv_set_option_string)
+#define mpv_set_option_string pfn_mpv_set_option_string
+MPV_DEFINE_SYM_PTR(mpv_command)
+#define mpv_command pfn_mpv_command
+MPV_DEFINE_SYM_PTR(mpv_command_node)
+#define mpv_command_node pfn_mpv_command_node
+MPV_DEFINE_SYM_PTR(mpv_command_ret)
+#define mpv_command_ret pfn_mpv_command_ret
+MPV_DEFINE_SYM_PTR(mpv_command_string)
+#define mpv_command_string pfn_mpv_command_string
+MPV_DEFINE_SYM_PTR(mpv_command_async)
+#define mpv_command_async pfn_mpv_command_async
+MPV_DEFINE_SYM_PTR(mpv_command_node_async)
+#define mpv_command_node_async pfn_mpv_command_node_async
+MPV_DEFINE_SYM_PTR(mpv_abort_async_command)
+#define mpv_abort_async_command pfn_mpv_abort_async_command
+MPV_DEFINE_SYM_PTR(mpv_set_property)
+#define mpv_set_property pfn_mpv_set_property
+MPV_DEFINE_SYM_PTR(mpv_set_property_string)
+#define mpv_set_property_string pfn_mpv_set_property_string
+MPV_DEFINE_SYM_PTR(mpv_del_property)
+#define mpv_del_property pfn_mpv_del_property
+MPV_DEFINE_SYM_PTR(mpv_set_property_async)
+#define mpv_set_property_async pfn_mpv_set_property_async
+MPV_DEFINE_SYM_PTR(mpv_get_property)
+#define mpv_get_property pfn_mpv_get_property
+MPV_DEFINE_SYM_PTR(mpv_get_property_string)
+#define mpv_get_property_string pfn_mpv_get_property_string
+MPV_DEFINE_SYM_PTR(mpv_get_property_osd_string)
+#define mpv_get_property_osd_string pfn_mpv_get_property_osd_string
+MPV_DEFINE_SYM_PTR(mpv_get_property_async)
+#define mpv_get_property_async pfn_mpv_get_property_async
+MPV_DEFINE_SYM_PTR(mpv_observe_property)
+#define mpv_observe_property pfn_mpv_observe_property
+MPV_DEFINE_SYM_PTR(mpv_unobserve_property)
+#define mpv_unobserve_property pfn_mpv_unobserve_property
+MPV_DEFINE_SYM_PTR(mpv_event_name)
+#define mpv_event_name pfn_mpv_event_name
+MPV_DEFINE_SYM_PTR(mpv_event_to_node)
+#define mpv_event_to_node pfn_mpv_event_to_node
+MPV_DEFINE_SYM_PTR(mpv_request_event)
+#define mpv_request_event pfn_mpv_request_event
+MPV_DEFINE_SYM_PTR(mpv_request_log_messages)
+#define mpv_request_log_messages pfn_mpv_request_log_messages
+MPV_DEFINE_SYM_PTR(mpv_wait_event)
+#define mpv_wait_event pfn_mpv_wait_event
+MPV_DEFINE_SYM_PTR(mpv_wakeup)
+#define mpv_wakeup pfn_mpv_wakeup
+MPV_DEFINE_SYM_PTR(mpv_set_wakeup_callback)
+#define mpv_set_wakeup_callback pfn_mpv_set_wakeup_callback
+MPV_DEFINE_SYM_PTR(mpv_wait_async_requests)
+#define mpv_wait_async_requests pfn_mpv_wait_async_requests
+MPV_DEFINE_SYM_PTR(mpv_hook_add)
+#define mpv_hook_add pfn_mpv_hook_add
+MPV_DEFINE_SYM_PTR(mpv_hook_continue)
+#define mpv_hook_continue pfn_mpv_hook_continue
+MPV_DEFINE_SYM_PTR(mpv_get_wakeup_pipe)
+#define mpv_get_wakeup_pipe pfn_mpv_get_wakeup_pipe
+
+#endif
+
#ifdef __cplusplus
}
#endif