From 92e129cc86b84bcd8e449a3422dfca885d926ee4 Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Fri, 23 Feb 2018 15:00:40 +0900 Subject: [PATCH] Implement c++ proxy generator (interface part) Change-Id: Ie47e0196d2e2e87f37b9352b88600c877517faca Signed-off-by: Junghoon Park --- idlc/cpp_gen/cpp_gen_base.cc | 502 +++++++++++++++++++++++++---------- idlc/cpp_gen/cpp_gen_base.h | 20 +- idlc/cpp_gen/cpp_gen_base_cb.h | 74 ++++++ idlc/cpp_gen/cpp_proxy_body_gen.cc | 189 ++++++++++++- idlc/cpp_gen/cpp_proxy_body_gen.h | 9 +- idlc/cpp_gen/cpp_proxy_body_gen_cb.h | 92 +++++++ idlc/cpp_gen/cpp_proxy_header_gen.cc | 104 +++++++- idlc/cpp_gen/cpp_proxy_header_gen.h | 6 + idlc/cpp_gen/cpp_stub_body_gen.cc | 3 - idlc/cpp_gen/cpp_stub_header_gen.cc | 2 + 10 files changed, 847 insertions(+), 154 deletions(-) create mode 100644 idlc/cpp_gen/cpp_gen_base_cb.h create mode 100644 idlc/cpp_gen/cpp_proxy_body_gen_cb.h diff --git a/idlc/cpp_gen/cpp_gen_base.cc b/idlc/cpp_gen/cpp_gen_base.cc index feae307..68f8813 100644 --- a/idlc/cpp_gen/cpp_gen_base.cc +++ b/idlc/cpp_gen/cpp_gen_base.cc @@ -19,6 +19,10 @@ #include "idlc/cpp_gen/cpp_gen_base.h" +namespace { +#include "cpp_gen_base_cb.h" +} + namespace tidl { CppGeneratorBase::CppGeneratorBase(std::shared_ptr doc) @@ -44,49 +48,7 @@ CppGeneratorBase::CppGeneratorBase(std::shared_ptr doc) } void CppGeneratorBase::GenStructuresForHeader(std::ofstream& stream) { - const char* cls = R"__cls_bundle(class Bundle final { - public: - Bundle() { - raw_ = bundle_create(); - } - - Bundle(bundle* b) { - raw_ = b; - } - - ~Bundle() { - if (raw_) - bundle_free(raw_); - } - - Bundle(Bundle&& b) : raw_(b.raw_) { - b.raw_ = nullptr; - } - - Bundle& operator = (Bundle&& b) { - raw_ = b.raw_; - b.raw_ = nullptr; - return *this; - } - - Bundle(const Bundle& b) : raw_(bundle_dup(b.GetHandle())) {} - - Bundle& operator = (const Bundle& b) { - raw_ = bundle_dup(b.GetHandle()); - return *this; - } - - bundle* GetHandle() const { - return raw_; - } - - private: - bundle* raw_; -}; - -)__cls_bundle"; - - stream << cls; + stream << CB_BUNDLE; for (auto& i : GetDocument().GetBlocks()) { if (i->GetType() != Block::TYPE_STRUCTURE) continue; @@ -96,30 +58,14 @@ void CppGeneratorBase::GenStructuresForHeader(std::ofstream& stream) { } } -void CppGeneratorBase::GenStructureForHeader(std::ofstream& stream, const Structure& st) { - std::vector p; - std::vector v; - std::vector lv; +void CppGeneratorBase::GenStructureForHeader(std::ofstream& stream, + const Structure& st) { const char ctor[] = " $$();\n" \ " $$($$);\n"; const char variable[] = "$$\n"; stream << "class " << st.GetID() << " final "; - for (auto& i : st.GetElements().GetElms()) { - if (i->GetType().GetMetaType() != nullptr) { - lv.push_back(ConvertTypeToString(i->GetType()) + " " + i->GetID()); - } - else { - if (i->GetType().IsUserDefinedType()) - p.push_back(i->GetType().ToString() + " " + i->GetID()); - else - p.push_back(ConvertTypeToString(i->GetType()) + " " + i->GetID()); - - v.push_back(ConvertTypeToString(i->GetType()) + " " + i->GetID()); - } - } - GenBrace(stream, 0, [&]() { stream << " public:" << NLine(1); GenTemplate(ctor, stream, @@ -131,11 +77,12 @@ void CppGeneratorBase::GenStructureForHeader(std::ofstream& stream, const Struct }, [&]()->std::string { std::string str; - for (auto& i : p) { - str += i; - - if (i != p.back()) + int n = 1; + for (auto& i : st.GetElements().GetElms()) { + if (n != 1) str += ", "; + str += ConvertTypeToString(i->GetType()) + " " + i->GetID(); + n++; } return str; } @@ -152,12 +99,12 @@ void CppGeneratorBase::GenStructureForHeader(std::ofstream& stream, const Struct GenTemplate(variable, stream, [&]()->std::string { std::string str; - for (auto& i : v) { - str += "\n" + Tab(1) + i + "_;"; - } - for (auto& i : lv) { - str += "\n" + Tab(1) + i + "_;"; + for (auto& i : st.GetElements().GetElms()) { + str += NLine(1) + Tab(1) + + ConvertTypeToString(i->GetType()) + " " + + i->GetID() + "_;"; } + str += NLine(1); return str; } ); @@ -241,18 +188,11 @@ void CppGeneratorBase::GenStructureForBody(std::ofstream& stream, const Structur " : $$ {}"; for (auto& i : st.GetElements().GetElms()) { - if (i->GetType().GetMetaType() == nullptr) { - std::pair p; - if (i->GetType().IsUserDefinedType()) { - p.first = i->GetType().ToString(); - p.second = i->GetID(); - } - else { - p.first = ConvertTypeToString(i->GetType()); - p.second = i->GetID(); - } - v.push_back(p); - } + std::pair p; + + p.first = ConvertTypeToString(i->GetType()); + p.second = i->GetID(); + v.push_back(p); } GenTemplate(ctor, stream, @@ -328,25 +268,9 @@ void CppGeneratorBase::GenSerializer(std::ofstream& stream, const Structure& st, stream << " "; GenBrace(stream, 0, [&]() { for (auto& i : st.GetElements().GetElms()) { - if (i->GetType().ToString() == "string") { - stream << Tab(1) << "rpc_port_parcel_write_" - << parcel_type_map_[i->GetType().ToString()] - << "(h, param.Get" << i->GetID() << "().c_str());" - << NLine(1); - } else if (i->GetType().ToString() == "bundle") { - stream << Tab(1) << "rpc_port_parcel_write_bundle(h, param.Get" - << i->GetID() << "().GetHandle());" << NLine(1); - } else if (i->GetType().GetMetaType() || - i->GetType().IsUserDefinedType()) { - stream << Tab(1) << "h << param.Get" << i->GetID() << "();" - << NLine(1); - } else { - stream << Tab(1) << "rpc_port_parcel_write_" - << parcel_type_map_[i->GetType().ToString()] - << "(h, param.Get" << i->GetID() << "());" - << NLine(1); - } - stream << NLine(1); + stream << AddIndent(TAB_SIZE, + ConvertTypeToSerializer(i->GetType(), + "param.Get" + i->GetID() + "()", "h")); } stream << Tab(1) << "return h;" << NLine(1); }, false); @@ -376,43 +300,10 @@ void CppGeneratorBase::GenDeSerializer(std::ofstream& stream, stream << " "; GenBrace(stream, 0, [&]() { for (auto& i : st.GetElements().GetElms()) { - if (i->GetType().ToString() == "string") { - stream << Tab(1) << "char* " << i->GetID() << " = nullptr;" << NLine(1); - stream << Tab(1) << "rpc_port_parcel_read_" - << parcel_type_map_[i->GetType().ToString()] - << "(h, &" << i->GetID() << ");" - << NLine(1); - stream << Tab(1) << "param.Set" << i->GetID() << "(" << i->GetID() << ");" - << NLine(1); - stream << Tab(1) << "free(" << i->GetID() << ");" - << NLine(1); - } else if (i->GetType().ToString() == "bundle") { - stream << Tab(1) << "bundle* " << i->GetID() << " = nullptr;" << NLine(1); - stream << Tab(1) << "rpc_port_parcel_read_" - << parcel_type_map_[i->GetType().ToString()] - << "(h, &" << i->GetID() << ");" - << NLine(1); - stream << Tab(1) << "param.Set" << i->GetID() << "(Bundle(" << i->GetID() << "));" - << NLine(1); - } else if (i->GetType().GetMetaType() != nullptr || - i->GetType().IsUserDefinedType()) { - stream << Tab(1) << ConvertTypeToString(i->GetType()) - << " " << i->GetID() << ";" << NLine(1); - stream << Tab(1) << "h >> " << i->GetID() << ";" - << NLine(1); - stream << Tab(1) << "param.Set" << i->GetID() << "(std::move(" << i->GetID() << "));" - << NLine(1); - } else { - stream << Tab(1) << ConvertTypeToString(i->GetType()) - << " " << i->GetID() << ";" << NLine(1); - stream << Tab(1) << "rpc_port_parcel_read_" - << parcel_type_map_[i->GetType().ToString()] - << "(h, &" << i->GetID() << ");" - << NLine(1); - stream << Tab(1) << "param.Set" << i->GetID() << "(" << i->GetID() << ");" - << NLine(1); - } - stream << NLine(1); + stream << AddIndent(TAB_SIZE, + ConvertTypeToDeserializer(i->GetType(), i->GetID(), "h")); + stream << Tab(1) << "param.Set" << i->GetID() << "(std::move(" << i->GetID() << "));" + << NLine(2); } stream << Tab(1) << "return h;" << NLine(1); }, false); @@ -533,4 +424,339 @@ void CppGeneratorBase::GenListSerializer(std::ofstream& stream, bool proto) { } } +void CppGeneratorBase::GenMethodId(std::ofstream& stream, + const Interface& iface) { + stream << Tab(1) << "enum class MethodId : int "; + GenBrace(stream, TAB_SIZE, [&]() { + int cnt = 2; + stream << Tab(2) << "Result = 0," << NLine(1); + stream << Tab(2) << "Callback = 1," << NLine(1); + for (auto& i : iface.GetDeclarations().GetDecls()) { + if (i->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + stream << Tab(2) + << i->GetID() << " = " << cnt++ << "," << NLine(1); + } + }, false, false); + stream << ";" << NLine(2); +} + +void CppGeneratorBase::GenDelegateId(std::ofstream& stream, + const Interface& iface) { + stream << Tab(1) << "enum class DelegateId : int "; + GenBrace(stream, TAB_SIZE, [&]() { + int cnt = 1; + for (auto& i : iface.GetDeclarations().GetDecls()) { + if (i->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + stream << Tab(2) + << i->GetID() << " = " << cnt++ << "," << NLine(1); + } + }, false, false); + stream << ";" << NLine(2); +} + +void CppGeneratorBase::GenParameters(std::ofstream& stream, + const Parameters& ps) { + bool first = true; + for (auto& i : ps.GetParams()) { + if (!first) { + stream << ", "; + } + + std::string ref; + auto dir = i->GetParameterType().GetDirection(); + if (dir == ParameterType::Direction::OUT || + dir == ParameterType::Direction::REF) { + ref = "&"; + } + + stream << ConvertTypeToString(i->GetParameterType().GetBaseType()) + << ref << " " << i->GetID(); + first = false; + } +} + +void CppGeneratorBase::GenDeclaration(std::ofstream& stream, + const Interface& iface, + const Declaration& decl) { + stream << ConvertTypeToString(decl.GetType()) << " " << iface.GetID() << "::" + << decl.GetID() << "("; + GenParameters(stream, decl.GetParameters()); + stream << ") "; +} + +std::string CppGeneratorBase::ConvertTypeToSerializer( + const BaseType& type, std::string id, std::string parcel) { + std::string ret; + + if (type.ToString() == "string") { + ret += "rpc_port_parcel_write_" + + parcel_type_map_[type.ToString()] + + "(" + parcel + ", " + id + ".c_str());\n"; + } else if (type.ToString() == "bundle") { + ret += "rpc_port_parcel_write_bundle(" + parcel + ", " + + id + ".GetHandle());\n"; + } else if (type.GetMetaType() || type.IsUserDefinedType()) { + ret += parcel + " << " + id + ";\n"; + } else { + ret += "rpc_port_parcel_write_" + + parcel_type_map_[type.ToString()] + + "(" + parcel + ", " + id + ");\n"; + } + + return ret; +} + +std::string CppGeneratorBase::ConvertTypeToDeserializer( + const BaseType& type, std::string id, std::string parcel, + bool make_new_type) { + std::string ret; + + if (type.ToString() == "string") { + ret += "char* " + id + "_raw = nullptr;\n"; + ret += "rpc_port_parcel_read_" + parcel_type_map_[type.ToString()] + + "(" + parcel + ", &" + id + "_raw);\n"; + if (make_new_type) { + ret += "std::string " + id + "(" + id + "_raw);\n"; + } else { + ret += id + " = " + id + "_raw;\n"; + } + ret += "free(" + id + "_raw);\n"; + } else if (type.ToString() == "bundle") { + ret += "bundle* " + id + "_raw = nullptr;\n"; + ret += "rpc_port_parcel_read_" + parcel_type_map_[type.ToString()] + + "(" + parcel + ", &" + id + "_raw);\n"; + if (make_new_type) { + ret += "Bundle " + id + "(" + id + "_raw);\n"; + } else { + ret += id + " = " + id + "_raw;\n" + + "bundle_free(" + id + "_raw);\n"; + } + } else if (type.GetMetaType() != nullptr || type.IsUserDefinedType()) { + std::string n; + + if (type.GetMetaType() != nullptr) + n = ConvertTypeToString(type); + else + n = type.ToString(); + + if (make_new_type) { + ret += n + " "; + if (IsDelegateType(type.ToString())) { + ret += id + "(port, std::weak_ptr(b));\n" + + "CallbackBase."; + } else { + ret += id + ";\n"; + } + } + ret += parcel + " >> " + id + ";\n"; + } else { + if (make_new_type) + ret += ConvertTypeToString(type) + " " + id + ";\n"; + ret += "rpc_port_parcel_read_" + parcel_type_map_[type.ToString()] + + "(" + parcel + ", &" + id + ");\n"; + } + + return ret; +} + +void CppGeneratorBase::GenBodyCallbacks(std::ofstream& stream, + const Interface& iface, bool is_proxy) { + GenTemplate(CB_CALLBACK_BASE, stream, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + } + ); + + for (auto& i : iface.GetDeclarations().GetDecls()) { + if (i->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + stream << NLine(1); + GenBodyCallback(stream, iface, *i, is_proxy); + } +} + +void CppGeneratorBase::GenBodyCallback(std::ofstream& stream, + const Interface& iface, const Declaration& decl, bool is_proxy) { + if (!is_proxy) { + const char method[] = "void $$::$$::Invoke()"; + + GenTemplate(method, stream, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return decl.GetID(); + } + ); + GenParameters(stream, decl.GetParameters()); + stream << ") "; + GenBrace(stream, 0, [&]() { + //TODO + + }, false); + } else { + const char cb[] = "void $$::$$::OnReceivedEvent(rpc_port_parcel_h parcel) "; + + GenTemplate(cb, stream, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return decl.GetID(); + } + ); + GenBrace(stream, 0, [&]() { + int cnt = 1; + for (auto& i : decl.GetParameters().GetParams()) { + std::string v = "param" + std::to_string(cnt); + std::string c = ConvertTypeToDeserializer( + i->GetParameterType().GetBaseType(), v, "parcel"); + stream << AddIndent(TAB_SIZE, c) << NLine(1); + cnt++; + } + + cnt = 1; + stream << Tab(1) << "OnReceived("; + for (int i = 0; i < decl.GetParameters().GetParams().size(); i++) { + if (cnt != 1) { + stream << ", "; + } + stream << "std::move(param" << std::to_string(cnt) << ")"; + cnt++; + } + stream << ");" << NLine(1); + }, false); + } +} + +void CppGeneratorBase::GenHeaderCallbacks(std::ofstream& stream, + const Interface& iface, + bool is_proxy) { + const char block1[] = + "class CallbackBase {\n" \ + " public:\n" \ + " CallbackBase(int delegate_id);\n" \ + " virtual ~CallbackBase() = default;\n" \ + "\n"; + + const char block2[] = + " int GetId() const;\n" \ + " int GetSeqId() const;\n" \ + "\n" \ + " private:\n" \ + " friend rpc_port_parcel_h operator << (rpc_port_parcel_h h, const CallbackBase& cb);\n" \ + " friend rpc_port_parcel_h operator >> (rpc_port_parcel_h h, CallbackBase& cb);\n" \ + "\n" \ + " static int seq_num_;\n" \ + " int id_;\n" \ + " int seq_id_;\n" \ + "};\n"; + + stream << AddIndent(TAB_SIZE, block1) << NLine(1); + if (is_proxy) { + stream << Tab(1) << " virtual void OnReceivedEvent(rpc_port_parcel_h port) = 0;" + << NLine(1); + } + stream << AddIndent(TAB_SIZE, block2) << NLine(1); + + for (auto& i : iface.GetDeclarations().GetDecls()) { + if (i->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + GenHeaderCallback(stream, *i, is_proxy); + } +} + +void CppGeneratorBase::GenHeaderCallback(std::ofstream& stream, + const Declaration& decl, + bool is_proxy) { + stream << Tab(1) << "class " << decl.GetID() + << " : public CallbackBase "; + GenBrace(stream, TAB_SIZE, [&]() { + const char ctor1[] = + "$$(rpc_port_parcel_h port, std::weak_ptr service)\n" \ + " : CallbackBase(static_cast(DelegateId::$$)) {\n" \ + " port_ = port;\n" \ + " service_ = std::move(service);\n" \ + "}\n"; + const char ctor2[] = + "$$()\n" \ + " : CallbackBase(static_cast(DelegateId::$$)) {}\n"; + + stream << Tab(1) << " public:" << NLine(1); + if (!is_proxy) { + GenTemplate(AddIndent(TAB_SIZE * 2, ctor1), stream, + [&]()->std::string { + return decl.GetID(); + }, + [&]()->std::string { + return decl.GetID(); + } + ); + } else { + GenTemplate(AddIndent(TAB_SIZE * 2, ctor2), stream, + [&]()->std::string { + return decl.GetID(); + }, + [&]()->std::string { + return decl.GetID(); + } + ); + } + stream << NLine(1); + if (is_proxy) { + stream << Tab(2) << "virtual void OnReceived("; + GenParameters(stream, decl.GetParameters()); + stream << ") {}" << NLine(1); + } else { + stream << Tab(2) << "void Invoke("; + GenParameters(stream, decl.GetParameters()); + stream << ");" << NLine(2); + } + + stream << Tab(1) << " private:" << NLine(1); + if (is_proxy) { + stream << Tab(2) << "void OnReceivedEvent(rpc_port_parcel_h port) override;" + << NLine(1); + } + stream << Tab(2) << "rpc_port_parcel_h port_;" << NLine(1); + if (!is_proxy) + stream << Tab(2) << "weak_ptr service_;" << NLine(1); + }, false, false); + stream << ";" << NLine(2); +} + +bool CppGeneratorBase::IsDelegateType(const std::string type_name) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_INTERFACE) + continue; + Interface& iface = static_cast(*i); + + for (auto& j : iface.GetDeclarations().GetDecls()) { + if (j->GetMethodType() == Declaration::MethodType::DELEGATE) { + if (j->GetID() == type_name) + return true; + } + } + } + + return false; +} + } // namespace tidl diff --git a/idlc/cpp_gen/cpp_gen_base.h b/idlc/cpp_gen/cpp_gen_base.h index 958d9ff..4a5058a 100644 --- a/idlc/cpp_gen/cpp_gen_base.h +++ b/idlc/cpp_gen/cpp_gen_base.h @@ -38,10 +38,24 @@ class CppGeneratorBase : public Generator { void GenDeSerializer(std::ofstream& stream); void GenListSerializer(std::ofstream& stream, bool proto = false); void GenPrototype(std::ofstream& stream); - + void GenMethodId(std::ofstream& stream, const Interface& iface); + void GenDelegateId(std::ofstream& stream, const Interface& iface); + void GenParameters(std::ofstream& stream, const Parameters& ps); + void GenDeclaration(std::ofstream& stream, const Interface& iface, + const Declaration& decl); + void GenBodyCallbacks(std::ofstream& stream, const Interface& iface, + bool is_proxy); + void GenHeaderCallbacks(std::ofstream& stream, const Interface& iface, + bool is_proxy); + bool IsDelegateType(const std::string type_name); std::string ConvertTypeToString(const BaseType& type); std::string Tab(int cnt); std::string NLine(int cnt); + std::string ConvertTypeToDeserializer(const BaseType& type, + std::string id, std::string parcel, + bool make_new_type = true); + std::string ConvertTypeToSerializer(const BaseType& type, + std::string id, std::string parcel); private: void GenSetter(std::ofstream& stream, const Element& ele); @@ -55,6 +69,10 @@ class CppGeneratorBase : public Generator { bool proto = false); void GenStructureForHeader(std::ofstream& stream, const Structure& st); void GenStructureForBody(std::ofstream& stream, const Structure& st); + void GenBodyCallback(std::ofstream& stream, const Interface& iface, + const Declaration& decl, bool is_proxy); + void GenHeaderCallback(std::ofstream& stream, const Declaration& decl, + bool is_proxy); protected: const int TAB_SIZE = 2; diff --git a/idlc/cpp_gen/cpp_gen_base_cb.h b/idlc/cpp_gen/cpp_gen_base_cb.h new file mode 100644 index 0000000..602fa75 --- /dev/null +++ b/idlc/cpp_gen/cpp_gen_base_cb.h @@ -0,0 +1,74 @@ +const char CB_BUNDLE[] = R"__cls_bundle(class Bundle final { + public: + Bundle() { + raw_ = bundle_create(); + } + + Bundle(bundle* b) { + raw_ = b; + } + + ~Bundle() { + if (raw_) + bundle_free(raw_); + } + + Bundle(Bundle&& b) : raw_(b.raw_) { + b.raw_ = nullptr; + } + + Bundle& operator = (Bundle&& b) { + raw_ = b.raw_; + b.raw_ = nullptr; + return *this; + } + + Bundle(const Bundle& b) : raw_(bundle_dup(b.GetHandle())) {} + + Bundle& operator = (const Bundle& b) { + raw_ = bundle_dup(b.GetHandle()); + return *this; + } + + bundle* GetHandle() const { + return raw_; + } + + private: + bundle* raw_; +}; + +)__cls_bundle"; + +const char CB_CALLBACK_BASE[] = +R"__cpp_cb( +int $$::CallbackBase::seq_num_ = 0; + +$$::CallbackBase::CallbackBase(int delegate_id) + : id_(delegate_id) { + seq_id_ = seq_num_++; +} + +int $$::CallbackBase::GetId() const { + return id_; +} + +int $$::CallbackBase::GetSeqId() const { + return seq_id_; +} + +rpc_port_parcel_h operator << (rpc_port_parcel_h h, const $$::CallbackBase& cb) { + rpc_port_parcel_write_int32(h, cb.id_); + rpc_port_parcel_write_int32(h, cb.seq_id_); + + return h; +} + +rpc_port_parcel_h operator >> (rpc_port_parcel_h h, $$::CallbackBase& cb) { + rpc_port_parcel_read_int32(h, &cb.id_); + rpc_port_parcel_read_int32(h, &cb.seq_id_); + + return h; +} + +)__cpp_cb"; \ No newline at end of file diff --git a/idlc/cpp_gen/cpp_proxy_body_gen.cc b/idlc/cpp_gen/cpp_proxy_body_gen.cc index 823035a..e136bc7 100644 --- a/idlc/cpp_gen/cpp_proxy_body_gen.cc +++ b/idlc/cpp_gen/cpp_proxy_body_gen.cc @@ -16,6 +16,10 @@ #include "idlc/cpp_gen/cpp_proxy_body_gen.h" +namespace { +#include "cpp_proxy_body_gen_cb.h" +} + namespace tidl { CppProxyBodyGen::CppProxyBodyGen(std::shared_ptr doc) @@ -32,9 +36,6 @@ void CppProxyBodyGen::OnInitGen(std::ofstream& stream) { stream << "#include " << NLine(1) << "#include " << NLine(1) << NLine(1) - << "#include " << NLine(1) - << "#include " << NLine(1) - << NLine(1) << "#include \"" << header_file << "\"" << NLine(2); GenNamespace(stream); } @@ -46,21 +47,191 @@ void CppProxyBodyGen::GenNamespace(std::ofstream& stream) { stream << "namespace rpc_port "; GenBrace(stream, 0, [&]() { stream << NLine(1); - GenPrototype(stream); GenStructuresForBody(stream); - GenSerializer(stream); - GenDeSerializer(stream); - GenListSerializer(stream); stream << "namespace proxy "; GenBrace(stream, 0, [&]() { -// GenInterfaces(stream); + GenPrototype(stream); + GenSerializer(stream); + GenDeSerializer(stream); + GenListSerializer(stream); + GenInterfaces(stream); }, false); }, false); } -void CppProxyBodyGen::GenConstructor(std::ofstream& stream) { +void CppProxyBodyGen::GenInterfaces(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_INTERFACE) + continue; + Interface& iface = static_cast(*i); + GenInterface(stream, iface); + } +} + +void CppProxyBodyGen::GenInterface(std::ofstream& stream, + const Interface& iface) { + GenBodyCallbacks(stream, iface, true); + GenConstructor(stream, iface); + GenDestructor(stream, iface); + GenHelperMethods(stream, iface); + GenMethods(stream, iface); +} + +void CppProxyBodyGen::GenConstructor(std::ofstream& stream, + const Interface& iface) { + GenTemplate(CB_PROXY_INTERFACE_CTOR, stream, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + } + ); +} + +void CppProxyBodyGen::GenDestructor(std::ofstream& stream, + const Interface& iface) { + const char cb[] = + "$$::~$$() {\n" \ + " if (proxy_)\n" \ + " rpc_port_proxy_destroy(proxy_);\n" \ + "}\n"; + + GenTemplate(cb, stream, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + } + ); +} + +void CppProxyBodyGen::GenHelperMethods(std::ofstream& stream, + const Interface& iface) { + + GenTemplate(CB_PROXY_HELPER_METHODS, stream, + [&]()->std::string { return iface.GetID(); }, + [&]()->std::string { return iface.GetID(); }, + [&]()->std::string { return iface.GetID(); }, + [&]()->std::string { return iface.GetID(); }, + [&]()->std::string { return iface.GetID(); }, + [&]()->std::string { return iface.GetID(); }, + [&]()->std::string { return iface.GetID(); }, + [&]()->std::string { return iface.GetID(); }, + [&]()->std::string { return iface.GetID(); }, + [&]()->std::string { return iface.GetID(); }, + [&]()->std::string { return iface.GetID(); }, + [&]()->std::string { return iface.GetID(); }, + [&]()->std::string { return iface.GetID(); }, + [&]()->std::string { return iface.GetID(); }, + [&]()->std::string { return iface.GetID(); }, + [&]()->std::string { return iface.GetID(); } + ); + stream << NLine(1); +} + +void CppProxyBodyGen::GenMethods(std::ofstream& stream, + const Interface& iface) { + auto& decls = iface.GetDeclarations(); + for (auto& i : decls.GetDecls()) { + if (i->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + + GenDeclaration(stream, iface, *i); + GenBrace(stream, 0, [&]() { + GenInvocation(stream, *i); + }, false); + stream << NLine(1); + } } +void CppProxyBodyGen::GenInvocation(std::ofstream& stream, const Declaration& decl) { + const char* pre = + "if (port_ == nullptr)\n" \ + " throw NotConnectedSocketException();\n" \ + "\n" \ + "rpc_port_parcel_h p;\n" \ + "rpc_port_parcel_create(&p);\n"; + + const char* mid = + "// Send\n" \ + "rpc_port_parcel_send(p, port_);\n"; + + stream << AddIndent(TAB_SIZE, pre); + + // Serialize + stream << Tab(1) + << "rpc_port_parcel_write_int32(p, static_cast(MethodId::" + << decl.GetID() << "));" << NLine(1); + std::string m; + std::string l; + for (auto& i : decl.GetParameters().GetParams()) { + auto& pt = i->GetParameterType(); + if (pt.GetDirection() == ParameterType::Direction::OUT) + continue; + m += ConvertTypeToSerializer(pt.GetBaseType(), i->GetID(), "p"); + if (IsDelegateType(pt.GetBaseType().ToString())) + l += "delegate_list_.emplace_back(new " + pt.GetBaseType().ToString() + + "(" + i->GetID() + "));\n"; + } + stream << AddIndent(TAB_SIZE, m) << NLine(1); + + if (decl.GetMethodType() == Declaration::MethodType::SYNC) + stream << Tab(1) << "rpc_port_parcel_h parcel_received;" << NLine(1); + stream << Tab(1) << "do "; + GenBrace(stream, TAB_SIZE, [&]() { + stream << Tab(2) << "std::lock_guard lock(mutex_);" + << NLine(2); + if (!l.empty()) + stream << AddIndent(TAB_SIZE * 2, l) << NLine(1); + stream << AddIndent(TAB_SIZE * 2, mid) << NLine(1); + if (decl.GetMethodType() == Declaration::MethodType::SYNC) { + stream << Tab(2) << "// Receive" << NLine(1); + stream << Tab(2) + << "ConsumeCommand(&parcel_received, port_);" << NLine(1); + } + }, false, false); + stream << " while (false);" << NLine(2); + + // Deserialize + if (decl.GetMethodType() == Declaration::MethodType::ASYNC) { + stream << Tab(1) << "rpc_port_parcel_destroy(p);" + << NLine(1); + return; + } + + const char* receive_block = + "if (parcel_received == nullptr) {\n" \ + " throw InvalidProtocolException();\n" \ + "}\n"; + stream << AddIndent(TAB_SIZE, receive_block) << NLine(1); + + for (auto& i : decl.GetParameters().GetParams()) { + if (i->GetParameterType().GetDirection() == ParameterType::Direction::IN) { + continue; + } + + std::string c = ConvertTypeToDeserializer( + i->GetParameterType().GetBaseType(), + i->GetID(), "parcel_received", false); + if (c != "") + stream << AddIndent(TAB_SIZE, c); + } + + if (decl.GetType().ToString() != "void") { + stream << AddIndent(TAB_SIZE, + ConvertTypeToDeserializer(decl.GetType(), + "ret", "parcel_received")); + } + + stream << Tab(1) << "rpc_port_parcel_destroy(p);" + << NLine(1); + stream << Tab(1) << "rpc_port_parcel_destroy(parcel_received);" + << NLine(1); + + stream << Tab(1) << "return ret;" << NLine(1); +} } // namespace tidl diff --git a/idlc/cpp_gen/cpp_proxy_body_gen.h b/idlc/cpp_gen/cpp_proxy_body_gen.h index eeacd33..0b6c6d4 100644 --- a/idlc/cpp_gen/cpp_proxy_body_gen.h +++ b/idlc/cpp_gen/cpp_proxy_body_gen.h @@ -35,8 +35,13 @@ class CppProxyBodyGen : public CppGeneratorBase { private: void GenNamespace(std::ofstream& stream); void GenStructures(std::ofstream& stream); - void GenConstructor(std::ofstream& stream); - void GenDestructor(std::ofstream& stream); + void GenInterfaces(std::ofstream& stream); + void GenInterface(std::ofstream& stream, const Interface& iface); + void GenConstructor(std::ofstream& stream, const Interface& iface); + void GenDestructor(std::ofstream& stream, const Interface& iface); + void GenHelperMethods(std::ofstream& stream, const Interface& iface); + void GenMethods(std::ofstream& stream, const Interface& iface); + void GenInvocation(std::ofstream& stream, const Declaration& decl); }; } // namespace tidl diff --git a/idlc/cpp_gen/cpp_proxy_body_gen_cb.h b/idlc/cpp_gen/cpp_proxy_body_gen_cb.h new file mode 100644 index 0000000..f431f5e --- /dev/null +++ b/idlc/cpp_gen/cpp_proxy_body_gen_cb.h @@ -0,0 +1,92 @@ +const char CB_PROXY_HELPER_METHODS[] = +R"__cpp_cb( +int $$::Connect() { + return rpc_port_proxy_connect(proxy_, target_appid_.c_str(), "$$"); +} + +void $$::ProcessReceivedEvent(rpc_port_parcel_h parcel) { + int id = 0; + int seqId = 0; + + rpc_port_parcel_read_int32(parcel, &id); + rpc_port_parcel_read_int32(parcel, &seqId); + + for (auto& i : delegate_list_) { + if (i->GetId() == id && i->GetSeqId() == seqId) { + i->OnReceivedEvent(parcel); + break; + } + } +} + +void $$::ConsumeCommand(rpc_port_parcel_h* parcel, rpc_port_h port) { + do { + rpc_port_parcel_h p; + int ret = rpc_port_parcel_create_from_port(&p, port); + int cmd; + + if (ret != 0) + break; + rpc_port_parcel_read_int32(p, &cmd); + if (cmd == static_cast(MethodId::Result)) { + *parcel = p; + return; + } + + ProcessReceivedEvent(p); + rpc_port_parcel_destroy(p); + *parcel = nullptr; + } while (true); + *parcel = nullptr; +} + +void $$::OnConnectedCB(const char *ep, const char *port_name, rpc_port_h port, void *data) { + $$* l = static_cast<$$*>(data); + l->port_ = port; + l->listener_->OnConnected(); +} + +void $$::OnDisconnectedCB(const char *ep, const char *port_name, void *data) { + $$* l = static_cast<$$*>(data); + l->listener_->OnDisconnected(); +} + +void $$::OnRejectedCB(const char *ep, const char *port_name, void *data) { + $$* l = static_cast<$$*>(data); + l->listener_->OnRejected(); +} + +void $$::OnReceivedCB(const char *ep, const char *port_name, void *data) { + $$* l = static_cast<$$*>(data); + int cmd; + rpc_port_parcel_h parcel_received; + + do { + std::lock_guard lock(l->mutex_); + if (rpc_port_parcel_create_from_port(&parcel_received, l->port_) != 0) + return; + } while (false); + + rpc_port_parcel_read_int32(parcel_received, &cmd); + if (cmd != static_cast(MethodId::Callback)) { + rpc_port_parcel_destroy(parcel_received); + throw InvalidProtocolException(); + } + + l->ProcessReceivedEvent(parcel_received); + rpc_port_parcel_destroy(parcel_received); +} +)__cpp_cb"; + +const char CB_PROXY_INTERFACE_CTOR[] = +R"__cpp_cb( +$$::$$(IEventListener* listener, const std::string& target_appid) + : port_(nullptr), proxy_(nullptr), listener_(listener), + target_appid_(target_appid) { + rpc_port_proxy_create(&proxy_); + rpc_port_proxy_add_connected_event_cb(proxy_, OnConnectedCB, this); + rpc_port_proxy_add_disconnected_event_cb(proxy_, OnDisconnectedCB, this); + rpc_port_proxy_add_rejected_event_cb(proxy_, OnRejectedCB, this); + rpc_port_proxy_add_received_event_cb(proxy_, OnReceivedCB, this); +} +)__cpp_cb"; diff --git a/idlc/cpp_gen/cpp_proxy_header_gen.cc b/idlc/cpp_gen/cpp_proxy_header_gen.cc index 761342d..3b30707 100644 --- a/idlc/cpp_gen/cpp_proxy_header_gen.cc +++ b/idlc/cpp_gen/cpp_proxy_header_gen.cc @@ -25,9 +25,13 @@ void CppProxyHeaderGen::OnInitGen(std::ofstream& stream) { stream << "#pragma once" << NLine(1) << NLine(1) << "#include " << NLine(1) + << "#include " << NLine(1) + << "#include " << NLine(2) << NLine(1) << "#include " << NLine(1) << "#include " << NLine(1) + << "#include " << NLine(1) + << "#include " << NLine(1) << "#include " << NLine(2); GenNamespace(stream); } @@ -42,9 +46,107 @@ void CppProxyHeaderGen::GenNamespace(std::ofstream& stream) { GenStructuresForHeader(stream); stream << "namespace proxy "; GenBrace(stream, 0, [&]() { -// GenInterfaces(stream); + GenExceptions(stream); + GenInterfaces(stream); }, false); }, false); } +void CppProxyHeaderGen::GenExceptions(std::ofstream& stream) { + const char cb[] = +R"__cpp_cb( +class Exception {}; +class NotConnectedSocketException : public Exception {}; +class InvalidProtocolException : public Exception {}; +)__cpp_cb"; + stream << cb << NLine(1); +} + +void CppProxyHeaderGen::GenInterfaces(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_INTERFACE) + continue; + Interface& iface = static_cast(*i); + GenInterface(stream, iface); + } +} + +void CppProxyHeaderGen::GenInterface(std::ofstream& stream, + const Interface& iface) { + const char* pub = + "class IEventListener {\n" \ + " public:\n" \ + " virtual void OnConnected() = 0;\n" \ + " virtual void OnDisconnected() = 0;\n" \ + " virtual void OnRejected() = 0;\n" \ + "};\n" + "\n" \ + "$$(IEventListener* listener, const std::string& target_appid);\n" \ + "virtual ~$$();\n" \ + "\n" \ + "int Connect();\n"; + + const char* priv = + "static void OnConnectedCB(const char *ep, const char *port_name,\n" \ + " rpc_port_h port, void *data);\n" \ + "static void OnDisconnectedCB(const char *ep, const char *port_name,\n" \ + " void *data);\n" \ + "static void OnRejectedCB(const char *ep, const char *port_name, void *data);\n" \ + "static void OnReceivedCB(const char *ep, const char *port_name, void *data);\n" \ + "\n" \ + "rpc_port_h port_;\n" \ + "rpc_port_proxy_h proxy_;\n" \ + "IEventListener* listener_;\n" \ + "std::recursive_mutex mutex_;\n" \ + "std::list> delegate_list_;\n" \ + "std::string target_appid_;\n"; + + stream << NLine(1) << "class " << iface.GetID() << " "; + GenBrace(stream, 0, [&]() { + stream << " public:" << NLine(1); + GenHeaderCallbacks(stream, iface, true); + GenTemplate(AddIndent(TAB_SIZE, pub), stream, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + } + ); + GenMethods(stream, iface); + stream << NLine(1) << " private:" << NLine(1); + GenMethodId(stream, iface); + GenDelegateId(stream, iface); + GenHelperMethods(stream); + stream << AddIndent(TAB_SIZE, priv); + }, false, false); + stream << ";" << NLine(1); +} + +void CppProxyHeaderGen::GenHelperMethods(std::ofstream& stream) { + const char* func = + "void ProcessReceivedEvent(rpc_port_parcel_h parcel);\n" \ + "void ConsumeCommand(rpc_port_parcel_h* parcel, rpc_port_h port);\n"; + stream << AddIndent(TAB_SIZE, func) << NLine(1); +} + +void CppProxyHeaderGen::GenMethods(std::ofstream& stream, + const Interface& iface) { + auto& decls = iface.GetDeclarations(); + + for (auto& i : decls.GetDecls()) { + if (i->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + + GenDeclaration(stream, *i); + } +} + +void CppProxyHeaderGen::GenDeclaration(std::ofstream& stream, + const Declaration& decl) { + stream << Tab(1) << ConvertTypeToString(decl.GetType()) << " " + << decl.GetID() << "("; + GenParameters(stream, decl.GetParameters()); + stream << ");" << NLine(1); +} } // namespace tidl diff --git a/idlc/cpp_gen/cpp_proxy_header_gen.h b/idlc/cpp_gen/cpp_proxy_header_gen.h index dc4b8df..0e120f8 100644 --- a/idlc/cpp_gen/cpp_proxy_header_gen.h +++ b/idlc/cpp_gen/cpp_proxy_header_gen.h @@ -34,6 +34,12 @@ class CppProxyHeaderGen : public CppGeneratorBase { private: void GenNamespace(std::ofstream& stream); + void GenExceptions(std::ofstream& stream); + void GenInterfaces(std::ofstream& stream); + void GenInterface(std::ofstream& stream, const Interface& iface); + void GenMethods(std::ofstream& stream, const Interface& iface); + void GenDeclaration(std::ofstream& stream, const Declaration& decl); + void GenHelperMethods(std::ofstream& stream); }; } // namespace tidl diff --git a/idlc/cpp_gen/cpp_stub_body_gen.cc b/idlc/cpp_gen/cpp_stub_body_gen.cc index c5cc0ca..78399c6 100644 --- a/idlc/cpp_gen/cpp_stub_body_gen.cc +++ b/idlc/cpp_gen/cpp_stub_body_gen.cc @@ -32,9 +32,6 @@ void CppStubBodyGen::OnInitGen(std::ofstream& stream) { stream << "#include " << NLine(1) << "#include " << NLine(1) << NLine(1) - << "#include " << NLine(1) - << "#include " << NLine(1) - << NLine(1) << "#include \"" << header_file << "\"" << NLine(2); GenNamespace(stream); } diff --git a/idlc/cpp_gen/cpp_stub_header_gen.cc b/idlc/cpp_gen/cpp_stub_header_gen.cc index 70996c7..8a36891 100644 --- a/idlc/cpp_gen/cpp_stub_header_gen.cc +++ b/idlc/cpp_gen/cpp_stub_header_gen.cc @@ -25,6 +25,8 @@ void CppStubHeaderGen::OnInitGen(std::ofstream& stream) { stream << "#pragma once" << NLine(1) << NLine(1) << "#include " << NLine(1) + << "#include " << NLine(1) + << "#include " << NLine(1) << NLine(1) << "#include " << NLine(1) << "#include " << NLine(1) -- 2.7.4