diff --git a/README.md b/README.md index afa31d4..04c2ada 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,8 @@ project/ │ │ ├── IpcConfig.h # type alias: using IpcMessage = BaseIpcMessage │ │ ├── IpcDispatcher.h │ │ ├── IpcPipeChannel.h +│ │ ├── IpcMarshaller.h │ │ └── IpcSerializer.h # сериализаторы (TextIpcSerializer) -│ ├── proxy/ -│ │ └── ProxyMarshaller.h │ └── rpc/ │ ├── rpc_export.h │ ├── RpcInvoker.h @@ -59,15 +58,15 @@ project/ * Сериализация вынесена в отдельные сериализаторы (`TextIpcSerializer` и т.д.) * Тип сырых данных параметризован через сериализатор (по умолчанию `std::string`, можно использовать `std::vector` для бинарных форматов) * Выбор сериализатора делается один раз в `IpcConfig.h` через type alias -* **Уровень канала**: `RpcChannel` + `IpcPipeChannel` +* **Уровень канала**: `IpcChannel` + `IpcPipeChannel` * `IpcChannel` — абстракция транспорта: `send(const IpcMessage&)`, `receive() -> IpcMessage`. * `IpcPipeChannel` — реализация поверх двух FIFO (`/tmp/fifo_to_server`, `/tmp/fifo_to_client`), которая внутри работает со строками, но наружу — только с `IpcMessage`. * **Уровень RPC-ядра**: - * `ProxyMarshaller` — собирает `IpcMessage` из имени метода и аргументов, отправляет через `RpcChannel` и читает ответ. + * `IpcMarshaller` — собирает `IpcMessage` из имени метода и аргументов, отправляет через `IpcChannel` и читает ответ. * `RpcInvoker` — по имени метода (первое поле сообщения) находит зарегистрированную функцию-член и вызывает её, читая аргументы через `get()`. * **Сгенерированные обёртки**: - * `*.proxy.*` — используют `ProxyMarshaller` и `RpcChannel`, не зависят от конкретного транспорта. - * `*.skeleton.*` — используют `RpcInvoker` и принимают/возвращают `IpcMessage` для диспетчеризации вызовов. + * `*.proxy.*` — шаблонные классы, зависящие только от абстрактного `impl` с методом `impl.callTyped(method, args...)` и не знающие про конкретный транспорт. + * `*.skeleton.*` — используют `RpcInvoker` и принимают/возвращают `RpcValue` для диспетчеризации вызовов. --- diff --git a/include/proxy/ProxyMarshaller.h b/include/ipc/IpcMarshaller.h similarity index 66% rename from include/proxy/ProxyMarshaller.h rename to include/ipc/IpcMarshaller.h index 30803e2..1cbf177 100644 --- a/include/proxy/ProxyMarshaller.h +++ b/include/ipc/IpcMarshaller.h @@ -4,9 +4,13 @@ #include #include -class ProxyMarshaller { +// Маршаллер, который знает, как превратить типизированный RPC-вызов +// в IpcMessage и обратно. Живёт в IPC-слое и опирается на IpcChannel +// и IpcCodec, но снаружи предъявляет только callTyped(...). +class IpcMarshaller { public: - explicit ProxyMarshaller(IpcChannel& ch) : channel(ch) {} + explicit IpcMarshaller(IpcChannel& ch) + : channel(ch) {} // Базовый type-erased вызов: принимает вектор RpcValue и возвращает RpcValue. RpcValue call(const std::string& method, const RpcArgs& args) { @@ -21,7 +25,7 @@ public: return IpcCodec::decodeResponse(resp); } - // Удобный шаблонный хелпер для сгенерированных прокси. + // Типизированный хелпер: контрактом является только наличие этого метода. template Ret callTyped(const std::string& method, const Args&... args) { RpcArgs packed; @@ -38,3 +42,4 @@ private: }; + diff --git a/src/client.cpp b/src/client.cpp index 9c6601c..cdb8c15 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1,6 +1,6 @@ #include "MyService.proxy.h" #include "ipc/IpcPipeChannel.h" -#include "proxy/ProxyMarshaller.h" +#include "ipc/IpcMarshaller.h" #include @@ -16,9 +16,9 @@ int main() { // и читает из fifo, в который пишет сервер (fifo_to_client). IpcPipeChannel ch("/tmp/fifo_to_client", "/tmp/fifo_to_server"); - // RPC‑уровень: создаём marshaller поверх канала и передаём его в прокси. - ProxyMarshaller marshaller(ch); - MyServiceProxy proxy(marshaller); + // RPC‑уровень: создаём IpcMarshaller поверх канала и передаём его в прокси. + IpcMarshaller marshaller(ch); + MyServiceProxy proxy(marshaller); proxy.add(7, 9); int counter = proxy.get(); diff --git a/tools/templates/proxy.cpp.j2 b/tools/templates/proxy.cpp.j2 index d5ccc04..62bfd6c 100644 --- a/tools/templates/proxy.cpp.j2 +++ b/tools/templates/proxy.cpp.j2 @@ -1,11 +1,5 @@ #include "{{ cls.name }}.proxy.h" -{{ cls.name }}Proxy::{{ cls.name }}Proxy(ProxyMarshaller& marshaller) - : impl(marshaller) {} - -{% for m in cls.methods %} -{{ m.return_type }} {{ cls.name }}Proxy::{{ m.name }}({% for a in m.args %}{{ a.type }} {{ a.name }}{% if not loop.last %}, {% endif %}{% endfor %}) { - return impl.callTyped<{{ m.return_type }}>("{{ cls.name }}.{{ m.name }}"{% for a in m.args %}, {{ a.name }}{% endfor %}); -} -{% endfor %} - +// Реализация шаблонного прокси целиком находится в заголовочном файле. +// Этот cpp остаётся пустым, чтобы сгенерированные файлы по‑прежнему +// могли участвовать в сборке как отдельная единица трансляции. diff --git a/tools/templates/proxy.h.j2 b/tools/templates/proxy.h.j2 index ce20106..9bdd0d6 100644 --- a/tools/templates/proxy.h.j2 +++ b/tools/templates/proxy.h.j2 @@ -1,14 +1,24 @@ #pragma once -#include "proxy/ProxyMarshaller.h" +#include "{{ cls.name }}.h" +// Шаблонный прокси, который зависит только от контракта Impl: +// Impl должен предоставлять метод +// template +// Ret callTyped(const std::string& method, const Args&... args); +template class {{ cls.name }}Proxy { public: - explicit {{ cls.name }}Proxy(ProxyMarshaller& marshaller); + explicit {{ cls.name }}Proxy(Impl& impl) + : impl(impl) {} + {% for m in cls.methods %} - {{ m.return_type }} {{ m.name }}({% for a in m.args %}{{ a.type }} {{ a.name }}{% if not loop.last %}, {% endif %}{% endfor %}); + {{ m.return_type }} {{ m.name }}({% for a in m.args %}{{ a.type }} {{ a.name }}{% if not loop.last %}, {% endif %}{% endfor %}) { + return impl.template callTyped<{{ m.return_type }}>("{{ cls.name }}.{{ m.name }}"{% for a in m.args %}, {{ a.name }}{% endfor %}); + } {% endfor %} private: - ProxyMarshaller& impl; + Impl& impl; }; +