TarsCpp icon indicating copy to clipboard operation
TarsCpp copied to clipboard

tars2cpp支持协程,为什么pb2tarscpp不支持协程

Open welsonzhang opened this issue 4 years ago • 1 comments

tars2cpp有生成对协程的支持,默认生成协程回调,但是pb2tarscpp,却没有生成对协程回调的支持,这个基于什么样的考虑呢?

welsonzhang avatar Feb 10 '20 06:02 welsonzhang

diff --git a/tools/pb2tarscpp/CppGenCallback.cpp b/tools/pb2tarscpp/CppGenCallback.cpp
index 63800cb..a5cb00f 100644
--- a/tools/pb2tarscpp/CppGenCallback.cpp
+++ b/tools/pb2tarscpp/CppGenCallback.cpp
@@ -157,3 +157,126 @@ std::string GenPrxCallback(const ::google::protobuf::ServiceDescriptor* desc, in
     return out;
 }
 
+std::string GenCoroPrxCallback(const ::google::protobuf::ServiceDescriptor* desc, int indent) {
+    std::string out;
+    out.reserve(8 * 1024);
+
+    const auto& name = desc->name();
+    const auto& pkg = desc->file()->package();
+    out += "/* callback of coroutine async proxy for client */";
+    out += LineFeed(indent);
+    out += "class " + name + "CoroPrxCallback : public "+ name + "PrxCallback" + LineFeed(indent);
+    out += "{";
+    out += LineFeed(indent);
+    out += "public:" + LineFeed(++indent) + "virtual ~" + name + "CoroPrxCallback() {}";
+    out += LineFeed(indent);
+    out += LineFeed(indent);
+
+    //sort by method name
+	std::map<std::string, const ::google::protobuf::MethodDescriptor*> m_method;
+	for (int i = 0; i < desc->method_count(); ++i)
+	{
+		m_method[desc->method(i)->name()] = desc->method(i);
+	}
+
+	for(auto it = m_method.begin(); it != m_method.end(); ++it)
+	{
+		auto method = it->second;
+		out += GenCallbackMethod(method, pkg, indent);
+	}
+
+    out += LineFeed(indent);
+    out += LineFeed(indent);
+
+    // gen onDispatch
+    out += LineFeed(indent);
+    out += LineFeed(indent);
+    out +=  "virtual int onDispatch(tars::ReqMessagePtr msg)";
+    out += LineFeed(indent);
+    out += "{";
+    out += LineFeed(++indent);
+    out += "static ::std::string __all[] = ";
+    out += "{";
+    out += LineFeed(++indent);
+    for(auto it = m_method.begin(); it != m_method.end(); ++it)
+	{
+    	auto method = it->second;
+        out += "\"" + method->name() + "\",";
+        out += LineFeed(indent);
+    }
+    out += LineFeed(--indent);
+    out += "};" + LineFeed(indent);
+    out += "pair<string*, string*> r = equal_range(__all, __all + " + std::to_string((long long)desc->method_count()) + ", " + "std::string(msg->request.sFuncName));";
+    out += LineFeed(indent);
+    out += "if(r.first == r.second) return tars::TARSSERVERNOFUNCERR;" + LineFeed(indent);
+    out += "switch(r.first - __all)" + LineFeed(indent);
+    out += "{";
+    out += LineFeed(++indent);
+    int i = 0;
+    for(auto it = m_method.begin(); it != m_method.end(); ++it)
+	{
+    	auto method = it->second;
+        out += LineFeed(indent);
+        out += "case " + std::to_string((long long)i) + ":" + LineFeed(indent);
+        out += "{" + LineFeed(++indent);
+        out += "if (msg->response.iRet != tars::TARSSERVERSUCCESS)" + LineFeed(indent);
+        out += "{" + LineFeed(++indent);
+        out += "callback_" + method->name() + "_exception(msg->response.iRet);" + LineFeed(indent);
+        out += "return msg->response.iRet;" + LineFeed(--indent) + "}";
+    
+        out += LineFeed(indent);
+        out += ToCppNamespace(method->output_type()->full_name()) + " _ret;" + LineFeed(indent);
+        out += "_ret.ParseFromArray(msg->response.sBuffer.data(), msg->response.sBuffer.size());" + LineFeed(indent);
+
+        out += "try" + LineFeed(indent);
+        out += "{" + LineFeed(indent);
+        out += LineFeed(++indent);
+        out += "setResponseContext(msg->response.context);" + LineFeed(indent);
+        out += "callback_" + method->name() + "(_ret);" + LineFeed(indent);
+        out += LineFeed(--indent);
+        out += "}" + LineFeed(indent);
+        out += "catch(std::exception &ex)" + LineFeed(indent);
+        out += "{" + LineFeed(indent);
+        out += LineFeed(++indent);
+        out += "callback_" +  method->name() + "_exception(tars::TARSCLIENTDECODEERR);" + LineFeed(indent);
+        out += "return tars::TARSCLIENTDECODEERR;" + LineFeed(indent);
+        out += LineFeed(--indent);
+        out += "}" + LineFeed(indent);
+        out += "catch(...)" + LineFeed(indent);
+        out += "{" + LineFeed(indent);
+        out += LineFeed(++indent);
+        out += "callback_" +  method->name() + "_exception(tars::TARSCLIENTDECODEERR);" + LineFeed(indent);
+        out += "return tars::TARSCLIENTDECODEERR;" + LineFeed(indent);
+        out += LineFeed(--indent);
+        out += "}" + LineFeed(indent);
+
+        out += "return tars::TARSSERVERSUCCESS;";
+
+        out += LineFeed(--indent);
+        out += "}";
+
+        ++i;
+    }
+
+    // end switch
+    out += LineFeed(--indent);
+    out += "}";
+
+    out += LineFeed(indent);
+    out += LineFeed(indent);
+    out += "return tars::TARSSERVERNOFUNCERR;";
+    out += LineFeed(--indent);
+    out += "}"; // end of onDispatch
+
+    out += "protected:" + LineFeed(indent);
+    out += LineFeed(++indent);
+    out += "map<std::string, std::string> _mRspContext;" + LineFeed(indent);
+    out += LineFeed(--indent);
+    out += "};"; // end of class CallbackPrx
+
+    out += LineFeed(indent);
+    out += "typedef tars::TC_AutoPtr<" + name + "PrxCallback> " + name + "PrxCallbackPtr;";
+    out += LineFeed(indent);
+
+    return out;
+}
diff --git a/tools/pb2tarscpp/CppGenCallback.h b/tools/pb2tarscpp/CppGenCallback.h
index 9bc843f..dcb121f 100644
--- a/tools/pb2tarscpp/CppGenCallback.h
+++ b/tools/pb2tarscpp/CppGenCallback.h
@@ -21,4 +21,6 @@ class ServiceDescriptor;
 
 // gen prx callback
 std::string GenPrxCallback(const ::google::protobuf::ServiceDescriptor* desc, int indent);
+// gen coro prx callback
+std::string GenCoroPrxCallback(const ::google::protobuf::ServiceDescriptor* desc, int indent);
 
diff --git a/tools/pb2tarscpp/CppGenProxy.cpp b/tools/pb2tarscpp/CppGenProxy.cpp
index 2298ad0..d370cb2 100644
--- a/tools/pb2tarscpp/CppGenProxy.cpp
+++ b/tools/pb2tarscpp/CppGenProxy.cpp
@@ -63,6 +63,27 @@ static std::string GenAsyncCall(const ::google::protobuf::MethodDescriptor* meth
     return out;
 }
 
+static std::string GenCoroCall(const ::google::protobuf::MethodDescriptor* method,
+                                const std::string& name,
+                                const std::string& pkg,
+                                int indent) {
+    std::string out;
+    out.reserve(8 * 1024);
+
+    out += "void coro_" + method->name() + "(" + name + "PrxCallbackPtr callback, const " +
+           ToCppNamespace(method->input_type()->full_name()) + "& req, const std::map<std::string, std::string>& context = TARS_CONTEXT())" + LineFeed(indent);
+    out += "{" + LineFeed(++indent);
+    out += "std::string _os;" + LineFeed(indent) +
+           "req.SerializeToString(&_os);" + LineFeed(indent) +
+           "std::vector<char> _vc(_os.begin(), _os.end());" + LineFeed(indent);
+    out += "std::map<std::string, std::string> _mStatus;" + LineFeed(indent);
+    out += "tars_invoke_async(tars::TARSNORMAL, \"" + method->name() + "\", _vc, context, _mStatus, callback, true);";
+    out += LineFeed(--indent) + "}";
+    out += LineFeed(indent);
+
+    return out;
+}
+
 std::string GenPrx(const ::google::protobuf::ServiceDescriptor* desc, int indent) {
     std::string out;
     out.reserve(8 * 1024);
@@ -98,6 +119,8 @@ std::string GenPrx(const ::google::protobuf::ServiceDescriptor* desc, int indent
 		out += GenSyncCall(method, pkg, indent);
 		// async method call
 		out += GenAsyncCall(method, name, pkg, indent);
+              // coro method call
+              out += GenCoroCall(method, name, pkg, indent);
 	}
 
 
diff --git a/tools/pb2tarscpp/CppPlugin.cpp b/tools/pb2tarscpp/CppPlugin.cpp
index 69a5aec..312d8cd 100644
--- a/tools/pb2tarscpp/CppPlugin.cpp
+++ b/tools/pb2tarscpp/CppPlugin.cpp
@@ -33,6 +33,7 @@ bool CppTarsGenerator::Generate(const google::protobuf::FileDescriptor *file,
     content += LineFeed(indent);
     for (int i = 0; i < file->service_count(); ++i) {
         content += GenPrxCallback(file->service(i), indent);
+        content += GenCoroPrxCallback(file->service(i), indent);
         content += GenPrx(file->service(i), indent);
         content += GenServant(file->service(i), indent);
     }

welsonzhang avatar Feb 11 '20 00:02 welsonzhang