From: Junghoon Park Date: Tue, 16 Jan 2018 11:02:40 +0000 (+0900) Subject: Support 'delegate' syntax X-Git-Tag: accepted/tizen/unified/20180302.061550~30 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4ed20064ed77b3b97fee4e36281049b04f32e955;p=platform%2Fcore%2Fappfw%2Ftidl.git Support 'delegate' syntax Change-Id: Ia1daf2d2ee9a4b5a36442b4f2c326bd8e1b435af Signed-off-by: Junghoon Park --- diff --git a/idlc/code_block/cs_proxy_interop.cb b/idlc/code_block/cs_proxy_interop.cb index c562f60..23fd141 100644 --- a/idlc/code_block/cs_proxy_interop.cb +++ b/idlc/code_block/cs_proxy_interop.cb @@ -12,6 +12,10 @@ [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate void RejectedEventCallback(string endPoint, string port_name, IntPtr data); + //typedef void (*rpc_port_proxy_received_event_cb) (const char* ep, const char* port_name, void* data); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ReceivedEventCallback(string endPoint, string port_name, IntPtr data); + //int rpc_port_proxy_create(rpc_port_proxy_h *h); [DllImport(Libraries.RpcPort, EntryPoint = "rpc_port_proxy_create")] internal static extern int Create(out IntPtr handle); @@ -35,4 +39,8 @@ //int rpc_port_proxy_add_rejected_event_cb(rpc_port_proxy_h h, rpc_port_proxy_rejected_event_cb cb, void* data); [DllImport(Libraries.RpcPort, EntryPoint = "rpc_port_proxy_add_rejected_event_cb")] internal static extern int AddRejectedEventCb(IntPtr handle, RejectedEventCallback cb, IntPtr data); + + //int rpc_port_proxy_add_received_event_cb(rpc_port_proxy_h h, rpc_port_proxy_received_event_cb cb, void* data); + [DllImport(Libraries.RpcPort, EntryPoint = "rpc_port_proxy_add_received_event_cb")] + internal static extern int AddReceivedEventCb(IntPtr handle, ReceivedEventCallback cb, IntPtr data); } diff --git a/idlc/cs_gen/cs_gen_base.cc b/idlc/cs_gen/cs_gen_base.cc index 6296b3c..3564f5e 100644 --- a/idlc/cs_gen/cs_gen_base.cc +++ b/idlc/cs_gen/cs_gen_base.cc @@ -26,7 +26,7 @@ CsGeneratorBase::CsGeneratorBase(std::shared_ptr doc) {"char", "byte"}, {"int", "int"}, {"short", "short"}, {"long", "long"}, {"string", "string"}, {"bool", "bool"}, {"list", "List"}, {"float","float"}, {"double", "double"}, - {"bundle", "Bundle"} + {"bundle", "Bundle"}, {"void", "void"} }; parcel_type_map_ = { @@ -269,6 +269,8 @@ std::string CsGeneratorBase::ConvertTypeToDeserializer( ret = n + " "; ret += id + " = new " + n +"();\n"; + if (IsDelegateType(type.ToString())) + ret += "CallbackBase."; ret += "Deserialize(" + parcel + ", " + id +");\n"; return ret; } @@ -295,6 +297,8 @@ std::string CsGeneratorBase::ConvertTypeToSerializer( if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) { + if (IsDelegateType(type.ToString())) + return "CallbackBase.Serialize(" + parcel + ", " + id + ");\n"; return "Serialize(" + parcel + ", " + id + ");\n"; } @@ -349,8 +353,26 @@ void CsGeneratorBase::GenWriteBundle(std::ofstream& stream, const std::string& i void CsGeneratorBase::GenMethodId(std::ofstream& stream, const Interface& iface) { stream << Tab(3) << "private enum MethodId : int" << NLine(1); GenBrace(stream, TAB_SIZE * 3, [&]() { + int cnt = 2; + stream << Tab(4) << "Result = 0," << NLine(1); + stream << Tab(4) << "Callback = 1," << NLine(1); + for (auto& i : iface.GetDeclarations().GetDecls()) { + if (i->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + stream << Tab(4) + << i->GetID() << " = " << cnt++ << "," << NLine(1); + } + }); + stream << NLine(1); +} + +void CsGeneratorBase::GenDelegateId(std::ofstream& stream, const Interface& iface) { + stream << Tab(3) << "private enum DelegateId : int" << NLine(1); + GenBrace(stream, TAB_SIZE * 3, [&]() { int cnt = 1; for (auto& i : iface.GetDeclarations().GetDecls()) { + if (i->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; stream << Tab(4) << i->GetID() << " = " << cnt++ << "," << NLine(1); } @@ -389,4 +411,164 @@ void CsGeneratorBase::GenParameters(std::ofstream& stream, const Parameters& ps) } } +void CsGeneratorBase::GenCallbacks(std::ofstream& stream, + const Interface& iface) { + const char block[] = + "public abstract class CallbackBase\n" \ + "{\n" \ + " internal int Id;\n" \ + " internal int SeqId;\n" \ + " private static int _seqNum = 0;\n" \ + "\n" \ + " public CallbackBase(int delegateId)\n" \ + " {\n" \ + " Id = delegateId;\n" \ + " SeqId = _seqNum++;\n" \ + " }\n" \ + "\n" \ + " internal abstract void OnReceivedEvent(IntPtr port);\n" \ + "\n" \ + " internal static void Serialize(IntPtr h, CallbackBase param)\n" \ + " {\n" \ + " Interop.LibRPCPort.Parcel.WriteInt32(h, (int)param.Id);\n" \ + " Interop.LibRPCPort.Parcel.WriteInt32(h, (int)param.SeqId);\n" \ + " }\n" \ + "\n" \ + " internal static void Deserialize(IntPtr h, CallbackBase param)\n" \ + " {\n" \ + " Interop.LibRPCPort.Parcel.ReadInt32(h, out var id);\n" \ + " param.Id = id;\n" \ + " Interop.LibRPCPort.Parcel.ReadInt32(h, out var seqId);\n" \ + " param.SeqId = seqId;\n" \ + " }\n" \ + "}\n"; + stream << AddIndent(TAB_SIZE * 3, block) << NLine(1); + + for (auto& i : iface.GetDeclarations().GetDecls()) { + if (i->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + GenCallback(stream, *i); + } +} + +void CsGeneratorBase::GenCallback(std::ofstream& stream, + const Declaration& decl) { + stream << Tab(3) << "public sealed class " << decl.GetID() + << " : CallbackBase" << NLine(1); + GenBrace(stream, TAB_SIZE * 3, [&]() { + const char ctor[] = + "public $$() : base((int)DelegateId.$$)\n" \ + "{\n" \ + "}\n" \ + "\n" \ + "internal $$(IntPtr port) : base((int)DelegateId.$$)\n" \ + "{\n" \ + " _port = port;\n" \ + "}\n"; + + GenTemplate(AddIndent(TAB_SIZE * 4, ctor), stream, + [&]()->std::string { + return decl.GetID(); + }, + [&]()->std::string { + return decl.GetID(); + }, + [&]()->std::string { + return decl.GetID(); + }, + [&]()->std::string { + return decl.GetID(); + } + ); + stream << NLine(1); + + stream << Tab(4) << "private IntPtr _port = IntPtr.Zero;" << NLine(1); + stream << Tab(4) << "public delegate void Callback("; + GenParameters(stream, decl.GetParameters()); + stream << ");" << NLine(1); + stream << Tab(4) << "public event Callback Received;" << NLine(2); + + GenReceivedEvent(stream, decl); + GenInvokeMethod(stream, decl); + }); + stream << NLine(1); +} + +void CsGeneratorBase::GenReceivedEvent(std::ofstream& stream, + const Declaration& decl) { + stream << Tab(4) << "internal override void OnReceivedEvent(IntPtr parcel)" + << NLine(1); + GenBrace(stream, TAB_SIZE * 4, [&]() { + 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 * 5, c); + cnt++; + } + + cnt = 1; + stream << Tab(5) << "Received?.Invoke("; + for (int i = 0; i < decl.GetParameters().GetParams().size(); i++) { + if (cnt != 1) { + stream << ", "; + } + std::string v = "param" + std::to_string(cnt); + stream << v; + cnt++; + } + stream << ");" << NLine(1); + }); + stream << NLine(1); +} + +void CsGeneratorBase::GenInvokeMethod(std::ofstream& stream, + const Declaration& decl) { + const char* pre = + "if (_port == IntPtr.Zero)\n" \ + " throw new InvalidOperationException(\"Not connected!\");\n" \ + "\n" \ + "Interop.LibRPCPort.Parcel.Create(out IntPtr p);\n" \ + "Interop.LibRPCPort.Parcel.WriteInt32(p, (int)MethodId.Callback);\n" \ + "Serialize(p, this);\n"; + + const char* mid = + "// Send\n" \ + "Interop.LibRPCPort.Parcel.Send(p, _port);\n" \ + "Interop.LibRPCPort.Parcel.Destroy(p);\n"; + + stream << Tab(4) << "public void Invoke("; + GenParameters(stream, decl.GetParameters()); + stream << ")" << NLine(1); + GenBrace(stream, TAB_SIZE * 4, [&]() { + stream << AddIndent(TAB_SIZE * 5, 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 * 5, m) << NLine(1); + stream << AddIndent(TAB_SIZE * 5, mid); + }); +} + +bool CsGeneratorBase::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/cs_gen/cs_gen_base.h b/idlc/cs_gen/cs_gen_base.h index 0c30a4a..d5865a2 100644 --- a/idlc/cs_gen/cs_gen_base.h +++ b/idlc/cs_gen/cs_gen_base.h @@ -39,9 +39,11 @@ class CsGeneratorBase : public Generator { void GenListSerializer(std::ofstream& stream); void GenListSerializer(std::ofstream& stream, const BaseType& type); void GenMethodId(std::ofstream& stream, const Interface& iface); + void GenDelegateId(std::ofstream& stream, const Interface& iface); void GenDeclaration(std::ofstream& stream, const Declaration& decl, bool semicol = true); void GenParameters(std::ofstream& stream, const Parameters& ps); + void GenCallbacks(std::ofstream& stream, const Interface& iface); std::string ConvertTypeToString(const BaseType& type); std::string ConvertTypeToDeserializer(const BaseType& type, @@ -50,6 +52,7 @@ class CsGeneratorBase : public Generator { std::string ConvertTypeToSerializer(const BaseType& type, std::string id, std::string parcel); std::string ConvertTypeToParcelType(const std::string& key); + bool IsDelegateType(const std::string type_name); std::string Tab(int cnt); std::string NLine(int cnt); @@ -59,6 +62,9 @@ class CsGeneratorBase : public Generator { private: void GenWriteBundle(std::ofstream& stream, const std::string& id); void AddSerializerList(const BaseType& type); + void GenCallback(std::ofstream& stream, const Declaration& decl); + void GenReceivedEvent(std::ofstream& stream, const Declaration& decl); + void GenInvokeMethod(std::ofstream& stream, const Declaration& decl); private: std::map type_map_; diff --git a/idlc/cs_gen/cs_proxy_gen.cc b/idlc/cs_gen/cs_proxy_gen.cc index 4edfbfb..4e03844 100644 --- a/idlc/cs_gen/cs_proxy_gen.cc +++ b/idlc/cs_gen/cs_proxy_gen.cc @@ -71,7 +71,12 @@ void CsProxyGen::GenInterface(std::ofstream& stream, const Interface& iface) { "private IntPtr _proxy;\n" \ "private IntPtr _port;\n" \ "private bool _online = false;\n" \ - "private string _appId;\n"; + "private string _appId;\n" \ + "private List _delegateList = new List();\n" \ + "private Interop.LibRPCPort.Proxy.ConnectedEventCallback _connectedEventCallback;\n" \ + "private Interop.LibRPCPort.Proxy.DisconnectedEventCallback _disconnectedEventCallback;\n" \ + "private Interop.LibRPCPort.Proxy.RejectedEventCallback _rejectedEventCallback;\n" \ + "private Interop.LibRPCPort.Proxy.ReceivedEventCallback _receivedEventCallback;\n"; const char* eventMethods = "private void OnConnectedEvent(string endPoint, string port_name, IntPtr port, IntPtr data)\n" \ @@ -89,12 +94,42 @@ void CsProxyGen::GenInterface(std::ofstream& stream, const Interface& iface) { "private void OnRejectedEvent(string endPoint, string port_name, IntPtr data)\n" \ "{\n" \ " Rejected?.Invoke(this, null);\n" \ + "}\n" \ + "\n" \ + "private void OnReceivedEvent(string endPoint, string port_name, IntPtr data)\n" \ + "{\n" \ + " if (Interop.LibRPCPort.Parcel.CreateFromPort(out IntPtr parcel_received, _port) != 0)\n" \ + " return;\n" \ + "\n" \ + " Interop.LibRPCPort.Parcel.ReadInt32(parcel_received, out int cmd);\n" \ + " if (cmd != (int)MethodId.Callback)\n" \ + " {\n" \ + " Interop.LibRPCPort.Parcel.Destroy(parcel_received);\n" \ + " //TODO\n" \ + " return;\n" \ + " }\n" \ + "\n" \ + " Interop.LibRPCPort.Parcel.ReadInt32(parcel_received, out int id);\n" \ + " Interop.LibRPCPort.Parcel.ReadInt32(parcel_received, out int seqId);\n" \ + "\n" \ + " foreach (var i in _delegateList)\n" \ + " {\n" \ + " if ((int)i.Id == id && i.SeqId == seqId)\n" \ + " {\n" \ + " i.OnReceivedEvent(parcel_received);\n" \ + " break;\n" \ + " }\n" \ + " }\n" \ + "\n" \ + " Interop.LibRPCPort.Parcel.Destroy(parcel_received);\n" \ "}\n"; stream << Tab(2) << "public class " << iface.GetID() << " : IDisposable" << NLine(1); GenBrace(stream, TAB_SIZE * 2, [&]() { stream << AddIndent(TAB_SIZE * 3, prop) << NLine(1); + GenCallbacks(stream, iface); + GenDelegateId(stream, iface); GenMethodId(stream, iface); stream << AddIndent(TAB_SIZE * 3, eventMethods) << NLine(1); GenSerializer(stream); @@ -122,9 +157,14 @@ void CsProxyGen::GenConnectMethod(std::ofstream& stream, const Interface& iface) "public void Connect()\n" \ "{\n" \ " Interop.LibRPCPort.Proxy.Create(out _proxy);\n" \ - " Interop.LibRPCPort.Proxy.AddConnectedEventCb(_proxy, OnConnectedEvent, IntPtr.Zero);\n" \ - " Interop.LibRPCPort.Proxy.AddDisconnectedEventCb(_proxy, OnDisconnectedEvent, IntPtr.Zero);\n" \ - " Interop.LibRPCPort.Proxy.AddRejectedEventCb(_proxy, OnRejectedEvent, IntPtr.Zero);\n" \ + " _connectedEventCallback = new Interop.LibRPCPort.Proxy.ConnectedEventCallback(OnConnectedEvent);\n" \ + " _disconnectedEventCallback = new Interop.LibRPCPort.Proxy.DisconnectedEventCallback(OnDisconnectedEvent);\n" \ + " _rejectedEventCallback = new Interop.LibRPCPort.Proxy.RejectedEventCallback(OnRejectedEvent);\n" \ + " _receivedEventCallback = new Interop.LibRPCPort.Proxy.ReceivedEventCallback(OnReceivedEvent);\n" \ + " Interop.LibRPCPort.Proxy.AddConnectedEventCb(_proxy, _connectedEventCallback, IntPtr.Zero);\n" \ + " Interop.LibRPCPort.Proxy.AddDisconnectedEventCb(_proxy, _disconnectedEventCallback, IntPtr.Zero);\n" \ + " Interop.LibRPCPort.Proxy.AddRejectedEventCb(_proxy, _rejectedEventCallback, IntPtr.Zero);\n" \ + " Interop.LibRPCPort.Proxy.AddReceivedEventCb(_proxy, _receivedEventCallback, IntPtr.Zero);\n" \ " if (Interop.LibRPCPort.Proxy.Connect(_proxy, _appId, \"$$\") != 0)\n" \ " throw new InvalidOperationException(\"Connection failed\");\n" \ "}"; @@ -178,6 +218,8 @@ void CsProxyGen::GenInvocation(std::ofstream& stream, const Declaration& decl) { if (pt.GetDirection() == ParameterType::Direction::OUT) continue; m += ConvertTypeToSerializer(pt.GetBaseType(), i->GetID(), "p"); + if (IsDelegateType(pt.GetBaseType().ToString())) + m += "_delegateList.Add(" + i->GetID() + ");\n"; } stream << AddIndent(TAB_SIZE * 4, m) << NLine(1); @@ -191,6 +233,15 @@ void CsProxyGen::GenInvocation(std::ofstream& stream, const Declaration& decl) { stream << Tab(4) << "Interop.LibRPCPort.Parcel.CreateFromPort(out IntPtr parcel_received, _port);" << NLine(1); + stream << Tab(4) + << "Interop.LibRPCPort.Parcel.ReadInt32(parcel_received, out int cmd);" + << NLine(1); + stream << Tab(4) + << "if (cmd != (int)MethodId.Result)" << NLine(1); + GenBrace(stream, TAB_SIZE * 4, [&]() { + //TODO + }); + stream << NLine(1); for (auto& i : decl.GetParameters().GetParams()) { if (i->GetParameterType().GetDirection() == ParameterType::Direction::IN) { diff --git a/idlc/cs_gen/cs_stub_gen.cc b/idlc/cs_gen/cs_stub_gen.cc index 64a6ced..63ef05a 100644 --- a/idlc/cs_gen/cs_stub_gen.cc +++ b/idlc/cs_gen/cs_stub_gen.cc @@ -65,14 +65,20 @@ void CsStubGen::GenInterfaces(std::ofstream& stream) { void CsStubGen::GenInterface(std::ofstream& stream, const Interface& iface) { stream << Tab(2) << "public sealed class " << iface.GetID() << NLine(1); GenBrace(stream, TAB_SIZE * 2, [&]() { - GenServiceBase(stream, iface); - stream << Tab(3) - << "private IntPtr _stub;" << NLine(2); + stream << Tab(3) << "private IntPtr _stub;" << NLine(1); stream << Tab(3) << "private List _services = new List();" + << NLine(1); + stream << Tab(3) << "private Type _serviceType;" << NLine(1); + stream << Tab(3) << "private Interop.LibRPCPort.Stub.ConnectedEventCallback _connectedEventCallback;" + << NLine(1); + stream << Tab(3) << "private Interop.LibRPCPort.Stub.DisconnectedEventCallback _disconnectedEventCallback;" + << NLine(1); + stream << Tab(3) << "private Interop.LibRPCPort.Stub.ReceivedEventCallback _receivedEventCallback;" << NLine(2); - stream << Tab(3) - << "private Type _serviceType;" << NLine(2); + GenServiceBase(stream, iface); + GenCallbacks(stream, iface); + GenDelegateId(stream, iface); GenMethodId(stream, iface); GenSerializer(stream); GenListSerializer(stream); @@ -108,6 +114,8 @@ void CsStubGen::GenServiceBase(std::ofstream& stream, const Interface& iface) { void CsStubGen::GenDeclarations(std::ofstream& stream, const Declarations& decls) { for (auto& i : decls.GetDecls()) { + if (i->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; stream << Tab(4) << "public abstract "; GenDeclaration(stream, *i); stream << NLine(1); @@ -218,7 +226,7 @@ void CsStubGen::GenInvocation(std::ofstream& stream, const Declaration& decl) { return; cnt = 0; - m = ""; + m = "Interop.LibRPCPort.Parcel.WriteInt32(result, (int)MethodId.Result);\n"; for (auto& i : decl.GetParameters().GetParams()) { auto& pt = i->GetParameterType(); cnt++; @@ -268,9 +276,12 @@ void CsStubGen::GenCtor(std::ofstream& stream, const Interface& iface) { "public $$()\n" \ "{\n" \ " Interop.LibRPCPort.Stub.Create(out _stub, \"$$\");\n" \ - " Interop.LibRPCPort.Stub.AddReceivedEventCb(_stub, OnReceivedEvent, IntPtr.Zero);\n" \ - " Interop.LibRPCPort.Stub.AddConnectedEventCb(_stub, OnConnectedEvent, IntPtr.Zero);\n" \ - " Interop.LibRPCPort.Stub.AddDisconnectedEventCb(_stub, OnDisconnectedEvent, IntPtr.Zero);\n"; + " _connectedEventCallback = new Interop.LibRPCPort.Stub.ConnectedEventCallback(OnConnectedEvent);\n" \ + " _disconnectedEventCallback = new Interop.LibRPCPort.Stub.DisconnectedEventCallback(OnDisconnectedEvent);\n" \ + " _receivedEventCallback = new Interop.LibRPCPort.Stub.ReceivedEventCallback(OnReceivedEvent);\n" \ + " Interop.LibRPCPort.Stub.AddReceivedEventCb(_stub, _receivedEventCallback, IntPtr.Zero);\n" \ + " Interop.LibRPCPort.Stub.AddConnectedEventCb(_stub, _connectedEventCallback, IntPtr.Zero);\n" \ + " Interop.LibRPCPort.Stub.AddDisconnectedEventCb(_stub, _disconnectedEventCallback, IntPtr.Zero);\n"; GenTemplate(AddIndent(TAB_SIZE * 3, ctor), stream, [&]()->std::string { diff --git a/idlc/tidlc.ll b/idlc/tidlc.ll index d9b235f..fb309a4 100644 --- a/idlc/tidlc.ll +++ b/idlc/tidlc.ll @@ -102,6 +102,7 @@ "out" { return yy::parser::token::T_OUT; } "ref" { return yy::parser::token::T_REF; } "async" { return yy::parser::token::T_ASYNC; } +"delegate" { return yy::parser::token::T_DELEGATE; } "<" { return yy::parser::token::T_META_OPEN; } ">" { return yy::parser::token::T_META_CLOSE; } "list" { @@ -129,7 +130,7 @@ return yy::parser::token::T_SB_CLOSE; } "=" { return yy::parser::token::T_EQUAL; } -"delegate" { return yy::parser::token::T_DELEGATE; } + %% diff --git a/idlc/tidlc.yy b/idlc/tidlc.yy index bc313f7..cb859a4 100644 --- a/idlc/tidlc.yy +++ b/idlc/tidlc.yy @@ -283,7 +283,7 @@ declaration: base_type T_ID T_LEFT parameter_list T_RIGHT T_SEMICOLON { delete $1; delete $2; } - | T_VOID T_ID T_LEFT parameter_list T_RIGHT T_DELEGATE T_SEMICOLON { + | T_VOID T_ID T_LEFT parameter_list T_RIGHT T_DELEGATE T_SEMICOLON { $$ = new tidl::Declaration($2->ToString(), new tidl::BaseType("void", $1->GetComments()), $4, $1->GetComments(), @1.begin.line,