diff --git a/src/wine-host/bridges/clap-impls/host-proxy.cpp b/src/wine-host/bridges/clap-impls/host-proxy.cpp
new file mode 100644
index 00000000..380eb76b
--- /dev/null
+++ b/src/wine-host/bridges/clap-impls/host-proxy.cpp
@@ -0,0 +1,60 @@
+// yabridge: a Wine plugin bridge
+// Copyright (C) 2020-2022 Robbert van der Helm
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+#include "host-proxy.h"
+
+#include "../../../common/serialization/clap/version.h"
+
+clap_host_proxy::clap_host_proxy(ClapBridge& bridge,
+ size_t owner_instance_id,
+ clap::host::Host host_args)
+ : bridge_(bridge),
+ owner_instance_id_(owner_instance_id),
+ host_args_(std::move(host_args)),
+ host_vtable_(clap_host_t{
+ .clap_version = clamp_clap_version(host_args_.clap_version),
+ .host_data = this,
+ .name = host_args_.name.c_str(),
+ .vendor = host_args_.vendor ? host_args_.vendor->c_str() : nullptr,
+ .url = host_args_.url ? host_args_.url->c_str() : nullptr,
+ .version = host_args_.version.c_str(),
+ .get_extension = host_get_extension,
+ .request_restart = host_request_restart,
+ .request_process = host_request_process,
+ .request_callback = host_request_callback,
+ }) {}
+
+const void* CLAP_ABI
+clap_host_proxy::host_get_extension(const struct clap_host* host,
+ const char* extension_id) {
+ // TODO: Implement
+ return nullptr;
+}
+
+void CLAP_ABI
+clap_host_proxy::host_request_restart(const struct clap_host* host) {
+ // TODO: Implement
+}
+
+void CLAP_ABI
+clap_host_proxy::host_request_process(const struct clap_host* host) {
+ // TODO: Implement
+}
+
+void CLAP_ABI
+clap_host_proxy::host_request_callback(const struct clap_host* host) {
+ // TODO: Implement
+}
diff --git a/src/wine-host/bridges/clap-impls/host-proxy.h b/src/wine-host/bridges/clap-impls/host-proxy.h
new file mode 100644
index 00000000..1324c8bd
--- /dev/null
+++ b/src/wine-host/bridges/clap-impls/host-proxy.h
@@ -0,0 +1,70 @@
+// yabridge: a Wine plugin bridge
+// Copyright (C) 2020-2022 Robbert van der Helm
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+#pragma once
+
+#include
+
+#include "../../common/serialization/clap/plugin-factory.h"
+
+// Forward declaration to avoid circular includes
+class ClapBridge;
+
+/**
+ * A proxy for a plugin's `clap_host`.
+ *
+ * Because the plugin may not query host extensions until `init()` is called,
+ * the available host extensions will only be populated at that point.
+ */
+class clap_host_proxy {
+ public:
+ /**
+ * Construct a host proxy based for a plugin. The available extensions will
+ * be populated when the host calls `clap_plugin::init()` as mentioned
+ * above.
+ */
+ clap_host_proxy(ClapBridge& bridge,
+ size_t owner_instance_id,
+ clap::host::Host host_args);
+
+ clap_host_proxy(const clap_host_proxy&) = delete;
+ clap_host_proxy& operator=(const clap_host_proxy&) = delete;
+ clap_host_proxy(clap_host_proxy&&) = delete;
+ clap_host_proxy& operator=(clap_host_proxy&&) = delete;
+
+ /**
+ * Get a `clap_host` vtable that can be passed to the plugin.
+ */
+ inline const clap_host_t* host_vtable() const { return &host_vtable_; }
+
+ static const void* CLAP_ABI host_get_extension(const struct clap_host* host,
+ const char* extension_id);
+ static void CLAP_ABI host_request_restart(const struct clap_host* host);
+ static void CLAP_ABI host_request_process(const struct clap_host* host);
+ static void CLAP_ABI host_request_callback(const struct clap_host* host);
+
+ private:
+ ClapBridge& bridge_;
+ size_t owner_instance_id_;
+ clap::host::Host host_args_;
+
+ /**
+ * The vtable for `clap_host`, requires that this object is never moved or
+ * copied. We'll use the host data pointer instead of placing this vtable at
+ * the start of the struct and directly casting the `clap_host_t*`.
+ */
+ const clap_host_t host_vtable_;
+};
diff --git a/src/wine-host/meson.build b/src/wine-host/meson.build
index 9fe04a23..94f217a3 100644
--- a/src/wine-host/meson.build
+++ b/src/wine-host/meson.build
@@ -81,6 +81,7 @@ if with_clap
host_sources += files(
'../common/logging/clap.cpp',
'../common/serialization/clap/plugin.cpp',
+ 'bridges/clap-impls/host-proxy.cpp',
'bridges/clap.cpp',
)
endif