From 165108e1c8ecd772b6b5492df34a20eef93d31b3 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Tue, 2 Sep 2025 09:59:47 +0800 Subject: [PATCH] safe call --- examples/client/main.cpp | 28 ++++++++++++++++++++++++--- include/rest_rpc/meta_util.hpp | 17 +++++++++++++++-- include/rest_rpc/rpc_client.hpp | 34 +++++++++++++++++++++++---------- 3 files changed, 64 insertions(+), 15 deletions(-) diff --git a/examples/client/main.cpp b/examples/client/main.cpp index bd12645..381e8cc 100644 --- a/examples/client/main.cpp +++ b/examples/client/main.cpp @@ -197,6 +197,11 @@ struct dummy1 { MSGPACK_DEFINE(id, str); }; +std::string echo(rpc_conn conn, const std::string &src); +struct dummy { + int add(rpc_conn conn, int a, int b); +}; + void test_echo() { rpc_client client("127.0.0.1", 9000); bool r = client.connect(); @@ -212,10 +217,27 @@ void test_echo() { } { - auto result = client.call("echo", "test"); + // safe call, same with `client.call("echo", "test")` + auto result = client.call("test"); std::cout << result << std::endl; } + { + // safe call member function + auto result = client.call<&dummy::add>(1, 2); + std::cout << result << std::endl; + } + + { + client.async_call( + "echo", + [](const asio::error_code &ec, string_view data) { + auto str = as(data); + std::cout << "echo " << str << '\n'; + }, + "test"); + } + { auto result = client.call("delay_echo", "test"); std::cout << result << std::endl; @@ -637,8 +659,8 @@ void benchmark_test() { int main() { // benchmark_test(); - test_connect(); - test_callback(); + // test_connect(); + // test_callback(); test_echo(); test_sync_client(); test_async_client(); diff --git a/include/rest_rpc/meta_util.hpp b/include/rest_rpc/meta_util.hpp index a2fe80e..abbb2b8 100644 --- a/include/rest_rpc/meta_util.hpp +++ b/include/rest_rpc/meta_util.hpp @@ -66,11 +66,15 @@ struct function_traits> template struct function_traits - : function_traits {}; + : function_traits { + using class_type = ClassType; +}; template struct function_traits - : function_traits {}; + : function_traits { + using class_type = ClassType; +}; template struct function_traits : function_traits {}; @@ -114,6 +118,15 @@ using nth_type_of = nonstd::tuple_element_t>; template using last_type_of = nth_type_of; + +template struct remove_first { using type = T; }; + +template +struct remove_first> { + using type = std::tuple; +}; + +template using remove_first_t = typename remove_first::type; } // namespace rest_rpc #endif // REST_RPC_META_UTIL_HPP diff --git a/include/rest_rpc/rpc_client.hpp b/include/rest_rpc/rpc_client.hpp index 61a040d..5e9359b 100644 --- a/include/rest_rpc/rpc_client.hpp +++ b/include/rest_rpc/rpc_client.hpp @@ -1,6 +1,7 @@ #pragma once #include "client_util.hpp" #include "const_vars.h" +#include "function_name.h" #include "md5.hpp" #include "meta_util.hpp" #include "use_asio.hpp" @@ -216,7 +217,7 @@ public: // sync call template typename std::enable_if::value>::type - call(const std::string &rpc_name, Args &&...args) { + call(std::string_view rpc_name, Args &&...args) { auto future_result = async_call(rpc_name, std::forward(args)...); auto status = future_result.wait_for(std::chrono::milliseconds(TIMEOUT)); @@ -230,13 +231,13 @@ public: template typename std::enable_if::value>::type - call(const std::string &rpc_name, Args &&...args) { + call(std::string_view rpc_name, Args &&...args) { call(rpc_name, std::forward(args)...); } template typename std::enable_if::value, T>::type - call(const std::string &rpc_name, Args &&...args) { + call(std::string_view rpc_name, Args &&...args) { auto future_result = async_call(rpc_name, std::forward(args)...); auto status = future_result.wait_for(std::chrono::milliseconds(TIMEOUT)); @@ -250,12 +251,23 @@ public: template typename std::enable_if::value, T>::type - call(const std::string &rpc_name, Args &&...args) { + call(std::string_view rpc_name, Args &&...args) { return call(rpc_name, std::forward(args)...); } + template auto call(Args &&...args) { + using args_tuple = typename function_traits::tuple_type; + static_assert(std::is_constructible_v, Args...>, + "called rpc function and arguments are not match"); + + constexpr auto rpc_name = get_func_name(); + using R = typename function_traits::return_type; + + return call(rpc_name, std::forward(args)...); + } + template - future_result async_call(const std::string &rpc_name, + future_result async_call(std::string_view rpc_name, Args &&...args) { auto p = std::make_shared>(); std::future future = p->get_future(); @@ -271,7 +283,7 @@ public: rpc_service::msgpack_codec codec; auto ret = codec.pack_args(std::forward(args)...); write(fu_id, request_type::req_res, std::move(ret), - MD5::MD5Hash32(rpc_name.data())); + MD5::MD5Hash32(rpc_name.data(), rpc_name.length())); return future_result{fu_id, std::move(future)}; } @@ -292,12 +304,13 @@ public: sbuffer.write(encoded_func_name_and_args.data(), encoded_func_name_and_args.size()); write(fu_id, request_type::req_res, std::move(sbuffer), - MD5::MD5Hash32(encoded_func_name_and_args.data())); + MD5::MD5Hash32(encoded_func_name_and_args.data(), + encoded_func_name_and_args.length())); return fu_id; } template - void async_call(const std::string &rpc_name, + void async_call(std::string_view rpc_name, std::function cb, Args &&...args) { if (!has_connected_) { @@ -321,7 +334,7 @@ public: rpc_service::msgpack_codec codec; auto ret = codec.pack_args(std::forward(args)...); write(cb_id, request_type::req_res, std::move(ret), - MD5::MD5Hash32(rpc_name.data())); + MD5::MD5Hash32(rpc_name.data(), rpc_name.length())); } void stop() { @@ -580,7 +593,8 @@ private: void send_subscribe(const std::string &key, const std::string &token) { rpc_service::msgpack_codec codec; auto ret = codec.pack_args(key, token); - write(0, request_type::sub_pub, std::move(ret), MD5::MD5Hash32(key.data())); + write(0, request_type::sub_pub, std::move(ret), + MD5::MD5Hash32(key.data(), key.length())); } void resend_subscribe() {