From 4ead87d7f7c0fa56b4f87ffeeb41b9ef64688c92 Mon Sep 17 00:00:00 2001 From: KerstinKeller Date: Mon, 20 Mar 2023 14:20:50 +0100 Subject: [PATCH] C#: Properly create protobuf descriptors (#1018) Properly create Protobuf descriptors when using newer Protobuf Versions which have that feature available. --- .../csharp/Continental/eCAL/Core/ecal_clr.cpp | 22 ++++++++- lang/csharp/Continental/eCAL/Core/ecal_clr.h | 18 +++++++ .../Continental/eCAL/Protobuf/CMakeLists.txt | 4 ++ .../Continental/eCAL/Protobuf/ProtoHelper.cs | 47 +++++++++++++++++-- .../eCAL/Protobuf/ProtoPublisher.cs | 2 +- 5 files changed, 85 insertions(+), 8 deletions(-) diff --git a/lang/csharp/Continental/eCAL/Core/ecal_clr.cpp b/lang/csharp/Continental/eCAL/Core/ecal_clr.cpp index 2d9154c83a..8f8a91f800 100644 --- a/lang/csharp/Continental/eCAL/Core/ecal_clr.cpp +++ b/lang/csharp/Continental/eCAL/Core/ecal_clr.cpp @@ -41,6 +41,14 @@ std::string StringToStlString(System::String^ s_) return(s); } +std::string ByteArrayToStlString(array^ array_) +{ + GCHandle handle = GCHandle::Alloc(array_, GCHandleType::Pinned); + size_t len = array_->Length; + std::string ret((const char*)(void*)handle.AddrOfPinnedObject(), len); + handle.Free(); + return(ret); +} ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// @@ -142,6 +150,11 @@ Publisher::Publisher(System::String^ topic_name_, System::String^ topic_type_, S m_pub = new ::eCAL::CPublisher(StringToStlString(topic_name_), StringToStlString(topic_type_), StringToStlString(topic_desc_)); } +Publisher::Publisher(System::String^ topic_name_, System::String^ topic_type_, array^ topic_desc_) +{ + m_pub = new ::eCAL::CPublisher(StringToStlString(topic_name_), StringToStlString(topic_type_), ByteArrayToStlString(topic_desc_)); +} + Publisher::~Publisher() { if(m_pub == nullptr) return; @@ -215,6 +228,11 @@ Subscriber::Subscriber(System::String^ topic_name_, System::String^ topic_type_, m_sub = new ::eCAL::CSubscriber(StringToStlString(topic_name_), StringToStlString(topic_type_), StringToStlString(topic_desc_)); } +Subscriber::Subscriber(System::String^ topic_name_, System::String^ topic_type_, array^ topic_desc_) +{ + m_sub = new ::eCAL::CSubscriber(StringToStlString(topic_name_), StringToStlString(topic_type_), ByteArrayToStlString(topic_desc_)); +} + Subscriber::~Subscriber() { if(m_sub == nullptr) return; @@ -291,7 +309,7 @@ bool Subscriber::AddReceiveCallback(ReceiverCallback^ callback_) return(true); } -bool Continental::eCAL::Core::Subscriber::AddReceiveCallback(ReceiverCallbackUnsafe^ callback_) +bool Subscriber::AddReceiveCallback(ReceiverCallbackUnsafe^ callback_) { if (m_sub == nullptr) return(false); if (m_callbacks_unsafe == nullptr) @@ -316,7 +334,7 @@ bool Subscriber::RemReceiveCallback(ReceiverCallback^ callback_) m_callbacks -= callback_; return(false); } -bool Continental::eCAL::Core::Subscriber::RemReceiveCallback(ReceiverCallbackUnsafe^ callback_) +bool Subscriber::RemReceiveCallback(ReceiverCallbackUnsafe^ callback_) { if (m_sub == nullptr) return(false); if (m_callbacks_unsafe == callback_) diff --git a/lang/csharp/Continental/eCAL/Core/ecal_clr.h b/lang/csharp/Continental/eCAL/Core/ecal_clr.h index 508669fa37..437c182637 100644 --- a/lang/csharp/Continental/eCAL/Core/ecal_clr.h +++ b/lang/csharp/Continental/eCAL/Core/ecal_clr.h @@ -159,6 +159,15 @@ namespace Continental **/ Publisher(System::String^ topic_name_, System::String^ topic_type_, System::String^ topic_desc_); + /** + * @brief Constructor. + * + * @param topic_name_ Unique topic name. + * @param topic_type_ Type name (optional. + * @param topic_desc_ Type description (optional. + **/ + Publisher(System::String^ topic_name_, System::String^ topic_type_, array^ topic_desc_); + /** * @brief Destructor. **/ @@ -257,6 +266,15 @@ namespace Continental **/ Subscriber(System::String^ topic_name_, System::String^ topic_type_, System::String^ topic_desc_); + /** + * @brief Constructor. + * + * @param topic_name_ Unique topic name. + * @param topic_type_ Type name (optional for type checking by monitoring app). + * @param topic_desc_ Descriptor (optional for dynamic reflection by monitoring app). + **/ + Subscriber(System::String^ topic_name_, System::String^ topic_type_, array^ topic_desc_); + /** * @brief Destructor. **/ diff --git a/lang/csharp/Continental/eCAL/Protobuf/CMakeLists.txt b/lang/csharp/Continental/eCAL/Protobuf/CMakeLists.txt index 4a96d40da4..8b690fdfda 100644 --- a/lang/csharp/Continental/eCAL/Protobuf/CMakeLists.txt +++ b/lang/csharp/Continental/eCAL/Protobuf/CMakeLists.txt @@ -35,6 +35,10 @@ set_target_properties(${PROJECT_NAME} PROPERTIES VS_DOTNET_TARGET_FRAMEWORK_VERSION "v4.6.1" ) +if (ECAL_CSHARP_PROTOBUF_VERSION VERSION_GREATER "3.16.0") +target_compile_definitions(${PROJECT_NAME} PRIVATE "ProtobufReflectionSupport") +endif() + set_property(TARGET ${PROJECT_NAME} PROPERTY VS_PACKAGE_REFERENCES "Google.Protobuf_${ECAL_CSHARP_PROTOBUF_VERSION}" ) diff --git a/lang/csharp/Continental/eCAL/Protobuf/ProtoHelper.cs b/lang/csharp/Continental/eCAL/Protobuf/ProtoHelper.cs index 2e804fbc26..68eaeeacb2 100644 --- a/lang/csharp/Continental/eCAL/Protobuf/ProtoHelper.cs +++ b/lang/csharp/Continental/eCAL/Protobuf/ProtoHelper.cs @@ -1,5 +1,4 @@ -using Google.Protobuf; -using System; +using System.Collections; namespace Continental { @@ -9,10 +8,48 @@ namespace Common { internal static class ProtobufHelper { - public static string GetProtoMessageDescription(Google.Protobuf.IMessage message) + +#if ProtobufReflectionSupport + public static void AddProtoDescriptor(Google.Protobuf.Reflection.FileDescriptorSet descriptor_set, Google.Protobuf.Reflection.FileDescriptor descriptor, System.Collections.Generic.HashSet inserted_files) + { + string name = descriptor.Name; + if (!inserted_files.Contains(name)) + { + inserted_files.Add(name); + foreach (var dependency in descriptor.Dependencies) + { + AddProtoDescriptor(descriptor_set, dependency, inserted_files); + } + descriptor_set.File.Add(descriptor.ToProto()); + } + } + + public static byte[] GetProtoMessageDescription(Google.Protobuf.IMessage message) + { + + var descriptor_set = new Google.Protobuf.Reflection.FileDescriptorSet(); + var descriptor = message.Descriptor.File; + var inserted_files = new System.Collections.Generic.HashSet(); + + AddProtoDescriptor(descriptor_set, descriptor, inserted_files); + + var memory_stream = new System.IO.MemoryStream(); + var stream = new Google.Protobuf.CodedOutputStream(memory_stream); + descriptor_set.WriteTo(stream); + stream.Flush(); + memory_stream.Flush(); + + byte[] descriptor_array = memory_stream.ToArray(); + return descriptor_array; + } +#else + public static byte[] GetProtoMessageDescription(Google.Protobuf.IMessage message) { - return ""; + return new byte[0]; } +#endif + + public static string GetProtoMessageTypeName(Google.Protobuf.IMessage message) { @@ -21,4 +58,4 @@ public static string GetProtoMessageTypeName(Google.Protobuf.IMessage message) } } } -} \ No newline at end of file +} diff --git a/lang/csharp/Continental/eCAL/Protobuf/ProtoPublisher.cs b/lang/csharp/Continental/eCAL/Protobuf/ProtoPublisher.cs index 75b95c38c3..88a1c9f583 100644 --- a/lang/csharp/Continental/eCAL/Protobuf/ProtoPublisher.cs +++ b/lang/csharp/Continental/eCAL/Protobuf/ProtoPublisher.cs @@ -35,7 +35,7 @@ public ProtobufPublisher(string topicName) public bool Send(T message) { var serialized = message.ToByteArray(); - return (binaryPublisher.Send(Encoding.Default.GetString(serialized), -1) > 0); + return (binaryPublisher.Send(serialized, -1) > 0); } } }