if (make_new_type) {
ret += n + " ";
if (IsDelegateType(type.ToString())) {
- ret += id + "(port, std::weak_ptr<ServiceBase>(b));\n"
- + "CallbackBase.";
+ ret += id + "(port, std::weak_ptr<ServiceBase>(b));\n";
} else {
ret += id + ";\n";
}
void CppGeneratorBase::GenBodyCallback(std::ofstream& stream,
const Interface& iface, const Declaration& decl, bool is_proxy) {
if (!is_proxy) {
- const char method[] = "void $$::$$::Invoke()";
+ const char method[] = "void $$::$$::Invoke(";
+
GenTemplate(method, stream,
[&]()->std::string {
GenParameters(stream, decl.GetParameters());
stream << ") ";
GenBrace(stream, 0, [&]() {
- //TODO
+ const char* pre =
+ "if (port_ == nullptr)\n" \
+ " throw NotConnectedSocketException();\n" \
+ "if (service_.lock().get() == nullptr)\n" \
+ " throw NotConnectedSocketException();\n" \
+ "\n" \
+ "rpc_port_parcel_h p;\n" \
+ "rpc_port_parcel_create(&p);\n" \
+ "rpc_port_parcel_write_int32(p, static_cast<int>(MethodId::Callback));\n" \
+ "p << *this;\n";
+
+ const char* mid =
+ "// Send\n" \
+ "rpc_port_parcel_send(p, port_);\n" \
+ "rpc_port_parcel_destroy(p);\n";
+
+ stream << AddIndent(TAB_SIZE, pre);
+ std::string m;
+ for (auto& i : decl.GetParameters().GetParams()) {
+ auto& pt = i->GetParameterType();
+ m += ConvertTypeToSerializer(pt.GetBaseType(), i->GetID(), "p");
+ }
+ stream << AddIndent(TAB_SIZE, m) << NLine(1);
+ stream << AddIndent(TAB_SIZE, mid);
}, false);
} else {
const char cb[] = "void $$::$$::OnReceivedEvent(rpc_port_parcel_h parcel) ";
}
stream << Tab(2) << "rpc_port_parcel_h port_;" << NLine(1);
if (!is_proxy)
- stream << Tab(2) << "weak_ptr<ServiceBase> service_;" << NLine(1);
+ stream << Tab(2) << "std::weak_ptr<ServiceBase> service_;" << NLine(1);
}, false, false);
stream << ";" << NLine(2);
}
stream << "namespace rpc_port ";
GenBrace(stream, 0, [&]() {
stream << NLine(1);
- GenPrototype(stream);
GenStructuresForBody(stream);
- GenSerializer(stream);
- GenDeSerializer(stream);
- GenListSerializer(stream);
stream << "namespace stub ";
GenBrace(stream, 0, [&]() {
-// GenInterfaces(stream);
+ GenPrototype(stream);
+ GenSerializer(stream);
+ GenDeSerializer(stream);
+ GenListSerializer(stream);
+ GenInterfaces(stream);
}, false);
}, false);
}
+void CppStubBodyGen::GenInterfaces(std::ofstream& stream) {
+ for (auto& i : GetDocument().GetBlocks()) {
+ if (i->GetType() != Block::TYPE_INTERFACE)
+ continue;
+ Interface& iface = static_cast<Interface&>(*i);
+ GenInterface(stream, iface);
+ }
+}
+
+void CppStubBodyGen::GenInterface(std::ofstream& stream,
+ const Interface& iface) {
+ GenServiceBase(stream, iface);
+ GenBodyCallbacks(stream, iface, false);
+ GenDefaultMethods(stream, iface);
+ GenReceivedEvent(stream, iface);
+}
+
+void CppStubBodyGen::GenServiceBase(std::ofstream& stream,
+ const Interface& iface) {
+ const char cb[] =
+ "$$::ServiceBase::ServiceBase(std::string sender, std::string instance)\n" \
+ " : sender_(std::move(sender)), instance_(std::move(instance)) {}\n" \
+ "\n";
+
+ GenTemplate(cb, stream,
+ [&]()->std::string {
+ return iface.GetID();
+ }
+ );
+ stream << NLine(1);
+}
+
+void CppStubBodyGen::GenDefaultMethods(std::ofstream& stream,
+ const Interface& iface) {
+ const char cb[] =
+R"__cpp_cb(
+$$::$$() {
+ rpc_port_stub_create(&stub_, "$$");
+ rpc_port_stub_add_connected_event_cb(stub_, OnConnectedCB, this);
+ rpc_port_stub_add_disconnected_event_cb(stub_, OnDisconnectedCB, this);
+ rpc_port_stub_add_received_event_cb(stub_, OnReceivedCB, this);
+}
+
+$$::~$$() {
+ if (stub_) {
+ rpc_port_stub_destroy(stub_);
+ }
+}
+
+void $$::Listen(
+ std::shared_ptr<$$::ServiceBase::Factory> service_factory) {
+ service_factory_ = std::move(service_factory);
+ rpc_port_stub_listen(stub_);
+}
+
+void $$::OnConnectedCB(const char* sender, const char* instance, void *data) {
+ $$* stub = static_cast<$$*>(data);
+ auto s = stub->service_factory_->CreateService(sender, instance);
+ s->OnCreate();
+ stub->services_.emplace_back(std::move(s));
+}
+
+void $$::OnDisconnectedCB(const char* sender, const char* instance, void *data) {
+ $$* stub = static_cast<$$*>(data);
+
+ for (auto& i : stub->services_) {
+ if (i->GetInstance() == instance) {
+ i->OnTerminate();
+ stub->services_.remove(i);
+ return;
+ }
+ }
+}
+)__cpp_cb";
+
+ GenTemplate(cb, 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(); }
+ );
+ stream << NLine(1);
+}
+
+void CppStubBodyGen::GenReceivedEvent(std::ofstream& stream,
+ const Interface& iface) {
+ const char method_front[] =
+ "int $$::OnReceivedCB(const char* sender, const char* instance, rpc_port_h port, void *data)\n" \
+ "{\n" \
+ " auto* cxt = static_cast<$$*>(data);"
+ " rpc_port_parcel_h p;\n" \
+ " rpc_port_parcel_h result;\n" \
+ " int cmd;\n" \
+ " int ret = rpc_port_parcel_create_from_port(&p, port);\n" \
+ "\n" \
+ " if (ret != 0)\n" \
+ " return ret;\n" \
+ "\n" \
+ " rpc_port_parcel_create(&result);\n" \
+ " rpc_port_parcel_read_int32(p, &cmd);\n" \
+ " std::shared_ptr<ServiceBase> b;\n" \
+ "\n" \
+ " for (auto& i : cxt->services_) {\n" \
+ " if (i->GetInstance() == instance) {\n" \
+ " b = i;\n" \
+ " break;\n" \
+ " }\n" \
+ " }\n" \
+ "\n" \
+ " if (b.get() == nullptr)\n" \
+ " return -1;\n" \
+ "\n"
+ " switch (cmd) {\n";
+
+ const char method_back[] =
+ " default:\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " rpc_port_parcel_destroy(p);\n" \
+ " rpc_port_parcel_destroy(result);\n" \
+ "\n" \
+ " return 0;\n" \
+ "}\n";
+
+ GenTemplate(method_front, stream,
+ [&]()->std::string {
+ return iface.GetID();
+ },
+ [&]()->std::string {
+ return iface.GetID();
+ }
+ );
+ for (auto& i : iface.GetDeclarations().GetDecls()) {
+ if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+ continue;
+ stream << Tab(2) << "case static_cast<int>(MethodId::" << i->GetID() << "): ";
+ GenBrace(stream, TAB_SIZE * 2, [&]() {
+ GenInvocation(stream, *i);
+ stream << Tab(3) << "break;" << NLine(1);
+ }, false);
+ stream << NLine(1);
+ }
+ stream << method_back << NLine(1);
+}
+
+void CppStubBodyGen::GenInvocation(std::ofstream& stream, const Declaration& decl) {
+ int cnt = 1;
+
+ // Deserialize
+ for (auto& i : decl.GetParameters().GetParams()) {
+ if (i->GetParameterType().GetDirection() == ParameterType::Direction::OUT) {
+ cnt++;
+ continue;
+ }
+
+ std::string v = "param" + std::to_string(cnt);
+ std::string c = ConvertTypeToDeserializer(
+ i->GetParameterType().GetBaseType(), v, "p");
+ stream << AddIndent(TAB_SIZE * 3, c);
+ cnt++;
+ }
+
+ // Invoke
+ cnt = 1;
+ std::string m;
+ bool hasRet = false;
+
+ if (decl.GetType().ToString() != "void") {
+ m += "auto retVal = ";
+ hasRet = true;
+ }
+
+ m += "b->" + decl.GetID() + "(";
+ for (auto& i : decl.GetParameters().GetParams()) {
+ if (cnt != 1) {
+ m += ", ";
+ }
+
+ std::string v = "param" + std::to_string(cnt);
+ auto& pt = i->GetParameterType();
+ if (pt.GetDirection() == ParameterType::Direction::OUT ||
+ pt.GetDirection() == ParameterType::Direction::REF) {
+ m += ConvertTypeToString(pt.GetBaseType()) + "& ";
+ }
+ m += v;
+ cnt++;
+ }
+
+ m += ");\n";
+ stream << AddIndent(TAB_SIZE * 3, m);
+
+ // Serialize
+ if (decl.GetMethodType() == Declaration::MethodType::ASYNC)
+ return;
+
+ cnt = 0;
+ m = "rpc_port_parcel_write_int32(result, static_cast<int>(MethodId::Result));\n";
+ for (auto& i : decl.GetParameters().GetParams()) {
+ auto& pt = i->GetParameterType();
+ cnt++;
+ if (pt.GetDirection() == ParameterType::Direction::IN)
+ continue;
+ m += ConvertTypeToSerializer(pt.GetBaseType(),
+ "param" + std::to_string(cnt), "result");
+ }
+
+ if (hasRet) {
+ m += ConvertTypeToSerializer(decl.GetType(), "retVal", "result");
+ }
+
+ m += "rpc_port_parcel_send(result, port);\n";
+ stream << AddIndent(TAB_SIZE * 3, m);
+}
+
} // namespace tidl
<< "#include <rpc-port-parcel.h>" << NLine(1)
<< "#include <rpc-port.h>" << NLine(1)
<< NLine(1)
+ << "#include <memory>" << NLine(1)
<< "#include <string>" << NLine(1)
<< "#include <vector>" << NLine(1)
<< "#include <list>" << NLine(2);
GenStructuresForHeader(stream);
stream << "namespace stub ";
GenBrace(stream, 0, [&]() {
-// GenInterfaces(stream);
+ GenExceptions(stream);
+ GenInterfaces(stream);
}, false);
}, false);
}
+
+void CppStubHeaderGen::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 CppStubHeaderGen::GenInterfaces(std::ofstream& stream) {
+ for (auto& i : GetDocument().GetBlocks()) {
+ if (i->GetType() != Block::TYPE_INTERFACE)
+ continue;
+ Interface& iface = static_cast<Interface&>(*i);
+ GenInterface(stream, iface);
+ }
+}
+
+void CppStubHeaderGen::GenInterface(std::ofstream& stream,
+ const Interface& iface) {
+ stream << NLine(1) << "class " << iface.GetID() << " final ";
+ GenBrace(stream, 0, [&]() {
+ GenPublic(stream, iface);
+ GenPrivate(stream, iface);
+ }, false, false);
+ stream << ";" << NLine(1);
+}
+
+void CppStubHeaderGen::GenPublic(std::ofstream& stream,
+ const Interface& iface) {
+ stream << " public:" << NLine(1);
+ stream << " class ServiceBase;" << NLine(1);
+ GenHeaderCallbacks(stream, iface, false);
+ GenServiceBase(stream, iface);
+ GenPublicMethods(stream, iface);
+}
+
+void CppStubHeaderGen::GenPrivate(std::ofstream& stream,
+ const Interface& iface) {
+ stream << " private:" << NLine(1);
+ GenMethodId(stream, iface);
+ GenDelegateId(stream, iface);
+
+ const char cb[] =
+ "static void OnConnectedCB(const char* sender, const char* instance, void* data);\n" \
+ "static void OnDisconnectedCB(const char* sender, const char* instance, void* data);\n" \
+ "static int OnReceivedCB(const char* sender, const char* instance, rpc_port_h port, void* data);\n" \
+ "\n" \
+ "rpc_port_stub_h stub_;\n" \
+ "std::shared_ptr<ServiceBase::Factory> service_factory_;\n" \
+ "std::list<std::shared_ptr<ServiceBase>> services_;\n";
+
+ stream << AddIndent(TAB_SIZE, cb);
+}
+
+void CppStubHeaderGen::GenServiceBase(std::ofstream& stream,
+ const Interface& iface) {
+ const char cb1[] = R"__cpp_cb( class ServiceBase {
+ public:
+ class Factory {
+ public:
+ virtual std::unique_ptr<ServiceBase> CreateService(std::string sender, std::string instance) = 0;
+ };
+
+ virtual ~ServiceBase() = default;
+
+ const std::string& GetSender() const {
+ return sender_;
+ }
+
+ const std::string& GetInstance() const {
+ return instance_;
+ }
+
+ virtual void OnCreate() = 0;
+ virtual void OnTerminate() = 0;
+)__cpp_cb";
+
+ const char cb2[] = R"__cpp_cb(
+ protected:
+ ServiceBase(std::string sender, std::string instance);
+
+ private:
+ std::string sender_;
+ std::string instance_;
+ };)__cpp_cb";
+
+ stream << cb1;
+ auto& decls = iface.GetDeclarations();
+
+ for (auto& i : decls.GetDecls()) {
+ if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+ continue;
+ stream << Tab(2) << "virtual " << ConvertTypeToString(i->GetType())
+ << " " << i->GetID() << "(";
+ GenParameters(stream, i->GetParameters());
+ stream << ") = 0;" << NLine(1);
+ }
+
+ stream << cb2 << NLine(2);
+}
+
+void CppStubHeaderGen::GenPublicMethods(std::ofstream& stream,
+ const Interface& iface) {
+ const char cb[] =
+ "$$();\n" \
+ "~$$();\n" \
+ "void Listen(std::shared_ptr<ServiceBase::Factory> service_factory);\n" \
+ "const std::list<std::shared_ptr<ServiceBase>>& GetServices() const {\n" \
+ " return services_;\n" \
+ "}\n";
+
+ GenTemplate(AddIndent(TAB_SIZE, cb), stream,
+ [&]()->std::string {
+ return iface.GetID();
+ },
+ [&]()->std::string {
+ return iface.GetID();
+ }
+ );
+ stream << NLine(1);
+}
+
} // namespace tidl