MineTrust Connector CPP SDK

MarshalUtils.h
1#pragma once
2
3#include <msclr/gcroot.h>
4#include <msclr/marshal.h>
5#include <msclr/marshal_cppstd.h>
6
7#include <chrono>
8
9using namespace System;
10
11// https://learn.microsoft.com/en-gb/cpp/dotnet/how-to-extend-the-marshaling-library?view=msvc-170#to-extend-the-marshaling-library-with-a-conversion-that-does-not-require-a-context
12
13namespace detail
14{
15 template <typename ToType>
16 struct MarshalTo
17 {
18 template <typename FromType>
19 static ToType From(const FromType& from)
20 {
21 return msclr::interop::marshal_as<ToType>(from);
22 }
23
24 // Marshall is not needed when type is the same
25 static ToType From(const ToType& from)
26 {
27 return from;
28 }
29 };
30
31 // Specialization for std::string to avoid exception in case of null string
32 template <>
33 struct MarshalTo<std::string>
34 {
35 static std::string From(String^ const & mString)
36 {
37 if (mString == nullptr)
38 {
39 return std::string();
40 }
41
42 return msclr::interop::marshal_as<std::string>(mString);
43 }
44
45 template <typename FromType>
46 static std::string From(const FromType& from)
47 {
48 return msclr::interop::marshal_as<std::string>(from);
49 }
50 };
51
52 // Specialization for integer conversion to managed enum type
53 template <>
54 struct MarshalTo<Datamine::MineTrustConnector::Core::LogEvent>
55 {
56 static Datamine::MineTrustConnector::Core::LogEvent From(MineTrustConnector::CppCliInterop::LogEvent value)
57 {
58 return static_cast<Datamine::MineTrustConnector::Core::LogEvent>(value);
59 }
60 };
61
62 // Specialization for integer conversion from managed enum type
63 template <>
64 struct MarshalTo<MineTrustConnector::CppCliInterop::LogEvent>
65 {
66 static MineTrustConnector::CppCliInterop::LogEvent From(Datamine::MineTrustConnector::Core::LogEvent value)
67 {
68 return static_cast<MineTrustConnector::CppCliInterop::LogEvent>(value);
69 }
70 };
71
72 template <typename ToDataType>
73 struct MarshalTo<std::unique_ptr<ToDataType>>
74 {
75 template <typename FromDataType>
76 static std::unique_ptr<ToDataType> From(System::Nullable<FromDataType> value)
77 {
78 std::unique_ptr<ToDataType> res;
79
80 if (value.HasValue)
81 {
82 res = std::make_unique<ToDataType>(MarshalTo<ToDataType>::From(value.Value));
83 }
84
85 return res;
86 }
87 };
88
89 template <typename ToDataType>
90 struct MarshalTo<System::Nullable<ToDataType>>
91 {
92 template <typename FromDataType>
93 static System::Nullable<ToDataType> From(const std::unique_ptr<FromDataType>& value)
94 {
95 if (value)
96 {
97 return System::Nullable<ToDataType>(MarshalTo<ToDataType>::From(*value));
98 }
99 else
100 {
101 return System::Nullable<ToDataType>();
102 }
103 }
104 };
105
106 // Specialization for STL containers
107 template <typename ToItemType>
108 struct MarshalTo<std::vector<ToItemType>>
109 {
110 template <typename FromType, typename ... ExtraArgs>
111 static auto From(FromType&& list, ExtraArgs&&... extraArgs)
112 {
113 std::vector<ToItemType> mList;
114
115 if (nullptr == list)
116 {
117 return mList;
118 }
119
120 for each (auto item in list)
121 {
122 mList.emplace_back(MarshalTo<ToItemType>::From(item, std::forward<ExtraArgs>(extraArgs)...));
123 }
124
125 return mList;
126 }
127 };
128
129 // Specialization for associative containers
130 template <typename ToKeyType, typename ToValueType>
131 struct MarshalTo<std::unordered_map<ToKeyType, ToValueType>>
132 {
133 template <typename FromType>
134 static auto From(FromType&& dictionary)
135 {
136 std::unordered_map<ToKeyType, ToValueType> mDictionary;
137
138 if (nullptr == dictionary)
139 {
140 return mDictionary;
141 }
142
143 mDictionary.reserve(dictionary->Count);
144
145 for each (auto dictionaryEntry in dictionary)
146 {
147 mDictionary[MarshalTo<ToKeyType>::From(dictionaryEntry.Key)] = MarshalTo<ToValueType>::From(dictionaryEntry.Value);
148 }
149
150 return mDictionary;
151 }
152 };
153
154 // Specialization for Managed containers
155 template <typename ToItemType>
156 struct MarshalTo<Collections::Generic::IEnumerable<ToItemType>^>
157 {
158 template <typename FromType, typename ... ExtraArgs>
159 static Collections::Generic::List<ToItemType>^ From(FromType&& list, ExtraArgs&&... extraArgs)
160 {
161 if (list.empty())
162 {
163 return nullptr;
164 }
165
166 auto mList = gcnew Collections::Generic::List<ToItemType>(static_cast<int>(list.size()));
167
168 for (const auto& item : list)
169 {
170 mList->Add(MarshalTo<ToItemType>::From(item, std::forward<ExtraArgs>(extraArgs)...));
171 }
172
173 return mList;
174 }
175 };
176
177 template <typename ToItemType>
178 struct MarshalTo<array<ToItemType>^>
179 {
180 template <typename FromType, typename ... ExtraArgs>
181 static array<ToItemType>^ From(FromType&& list, ExtraArgs&&... extraArgs)
182 {
183 if (list.empty())
184 {
185 return nullptr;
186 }
187
188 auto mArray = gcnew array<ToItemType>(static_cast<int>(list.size()));
189 int index = 0;
190
191 for (const auto& item : list)
192 {
193 mArray[index] = MarshalTo<ToItemType>::From(item, std::forward<ExtraArgs>(extraArgs)...);
194 ++index;
195 }
196
197 return mArray;
198 }
199 };
200
201 // Specialization for Managed associative containers
202 template <typename ToKeyType, typename ToValueType>
203 struct MarshalTo<Collections::Generic::IDictionary<ToKeyType, ToValueType>^>
204 {
205 template <typename FromType>
206 static Collections::Generic::Dictionary<ToKeyType, ToValueType>^ From(FromType&& dictionary)
207 {
208 if (dictionary.empty())
209 {
210 return nullptr;
211 }
212
213 auto mDictionary = gcnew Collections::Generic::Dictionary<ToKeyType, ToValueType>();
214
215 for (const auto& it : dictionary)
216 {
217 mDictionary[MarshalTo<ToKeyType>::From(it.first)] = MarshalTo<ToValueType>::From(it.second);
218 }
219
220 return mDictionary;
221 }
222 };
223
224 // Specialization for std::chrono::system_clock::time_point <-> DateTime
225 template <>
226 struct MarshalTo<std::chrono::system_clock::time_point>
227 {
228 // https://stackoverflow.com/a/39460722
229
230 using clock = std::chrono::system_clock;
231 using duration = clock::duration;
232 using time_point = clock::time_point;
233
234 static time_point From(DateTime value)
235 {
236 const DateTime epochCpp(1970, 1, 1);
237 const DateTime epochClr(1, 1, 1);
238 const TimeSpan epochDiff = epochCpp - epochClr;
239 return time_point(duration((value - epochDiff).Ticks));
240 }
241 };
242}
243
244template <typename ToType, typename FromType, typename ... ExtraArgs>
245ToType Marshal(const FromType& fromObject, ExtraArgs&&... extraArgs)
246{
247 return detail::MarshalTo<ToType>::From(fromObject, std::forward<ExtraArgs>(extraArgs)...);
248}
249
250template <typename ManagedType>
251msclr::gcroot<ManagedType^> MakeGcRoot(ManagedType^ managedType)
252{
253 return managedType;
254}
LogEvent
Definition CppCliInterop.h:32
Definition MarshalUtils.h:17