BsMonoUtil.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsMonoUtil.h"
  4. #include "Debug/BsDebug.h"
  5. #include <mono/jit/jit.h>
  6. #include <codecvt>
  7. namespace bs
  8. {
  9. WString MonoUtil::monoToWString(MonoString* str)
  10. {
  11. if (str == nullptr)
  12. return StringUtil::WBLANK;
  13. int len = mono_string_length(str);
  14. mono_unichar2* monoChars = mono_string_chars(str);
  15. WString ret(len, '0');
  16. for (int i = 0; i < len; i++)
  17. ret[i] = monoChars[i];
  18. return ret;
  19. }
  20. String MonoUtil::monoToString(MonoString* str)
  21. {
  22. if (str == nullptr)
  23. return StringUtil::BLANK;
  24. int len = mono_string_length(str);
  25. mono_unichar2* monoChars = mono_string_chars(str);
  26. String ret(len, '0');
  27. for (int i = 0; i < len; i++)
  28. ret[i] = (char)monoChars[i];
  29. return ret;
  30. }
  31. MonoString* MonoUtil::wstringToMono(const WString& str)
  32. {
  33. if (sizeof(wchar_t) == 2) // Assuming UTF-16
  34. return mono_string_from_utf16((mono_unichar2*)str.c_str());
  35. else // Assuming UTF-32
  36. {
  37. const std::codecvt_mode convMode = (std::codecvt_mode)(std::little_endian);
  38. typedef std::codecvt_utf16<UINT32, 1114111, convMode> utf16utf32;
  39. std::wstring_convert<utf16utf32, UINT32> conversion("?");
  40. UINT32* start = (UINT32*)str.data();
  41. UINT32* end = (start + (str.size() - 1) / 4);
  42. mono_unichar2* convertedStr = (mono_unichar2*)conversion.to_bytes(start, end).c_str();
  43. return mono_string_from_utf16(convertedStr);
  44. }
  45. }
  46. MonoString* MonoUtil::stringToMono(const String& str)
  47. {
  48. return wstringToMono(toWString(str));
  49. }
  50. void MonoUtil::getClassName(MonoObject* obj, String& ns, String& typeName)
  51. {
  52. if (obj == nullptr)
  53. return;
  54. ::MonoClass* monoClass = mono_object_get_class(obj);
  55. getClassName(monoClass, ns, typeName);
  56. }
  57. void MonoUtil::getClassName(::MonoClass* monoClass, String& ns, String& typeName)
  58. {
  59. ::MonoClass* nestingClass = mono_class_get_nesting_type(monoClass);
  60. if (nestingClass == nullptr)
  61. {
  62. ns = mono_class_get_namespace(monoClass);
  63. typeName = mono_class_get_name(monoClass);
  64. return;
  65. }
  66. else
  67. {
  68. typeName = String("+") + mono_class_get_name(monoClass);
  69. do
  70. {
  71. ::MonoClass* nextNestingClass = mono_class_get_nesting_type(nestingClass);
  72. if (nextNestingClass != nullptr)
  73. {
  74. typeName = String("+") + mono_class_get_name(nestingClass) + typeName;
  75. nestingClass = nextNestingClass;
  76. }
  77. else
  78. {
  79. ns = mono_class_get_namespace(nestingClass);
  80. typeName = mono_class_get_name(nestingClass) + typeName;
  81. break;
  82. }
  83. } while (true);
  84. }
  85. }
  86. void MonoUtil::getClassName(MonoReflectionType* monoReflType, String& ns, String& typeName)
  87. {
  88. MonoType* monoType = mono_reflection_type_get_type(monoReflType);
  89. ::MonoClass* monoClass = mono_type_get_class(monoType);
  90. getClassName(monoClass, ns, typeName);
  91. }
  92. ::MonoClass* MonoUtil::getClass(MonoObject* object)
  93. {
  94. return mono_object_get_class(object);
  95. }
  96. ::MonoClass* MonoUtil::getClass(MonoReflectionType* type)
  97. {
  98. MonoType* monoType = mono_reflection_type_get_type(type);
  99. return mono_type_get_class(monoType);
  100. }
  101. MonoReflectionType* MonoUtil::getType(MonoObject* object)
  102. {
  103. ::MonoClass* klass = getClass(object);
  104. return getType(klass);
  105. }
  106. MonoReflectionType* MonoUtil::getType(::MonoClass* klass)
  107. {
  108. MonoType* monoType = mono_class_get_type(klass);
  109. return mono_type_get_object(MonoManager::instance().getDomain(), monoType);
  110. }
  111. UINT32 MonoUtil::newGCHandle(MonoObject* object)
  112. {
  113. return mono_gchandle_new(object, false);
  114. }
  115. void MonoUtil::freeGCHandle(UINT32 handle)
  116. {
  117. mono_gchandle_free(handle);
  118. }
  119. MonoObject* MonoUtil::box(::MonoClass* klass, void* value)
  120. {
  121. return mono_value_box(MonoManager::instance().getDomain(), klass, value);
  122. }
  123. void* MonoUtil::unbox(MonoObject* object)
  124. {
  125. return mono_object_unbox(object);
  126. }
  127. bool MonoUtil::isSubClassOf(::MonoClass* subClass, ::MonoClass* parentClass)
  128. {
  129. return mono_class_is_subclass_of(subClass, parentClass, true) != 0;
  130. }
  131. bool MonoUtil::isValueType(::MonoClass* klass)
  132. {
  133. return mono_class_is_valuetype(klass) != 0;
  134. }
  135. bool MonoUtil::isEnum(::MonoClass* object)
  136. {
  137. return mono_class_is_enum(object) != 0;
  138. }
  139. MonoPrimitiveType MonoUtil::getEnumPrimitiveType(::MonoClass* enumClass)
  140. {
  141. MonoType* monoType = mono_class_get_type(enumClass);
  142. MonoType* underlyingType = mono_type_get_underlying_type(monoType);
  143. return getPrimitiveType(mono_type_get_class(underlyingType));
  144. }
  145. MonoPrimitiveType MonoUtil::getPrimitiveType(::MonoClass* monoClass)
  146. {
  147. MonoType* monoType = mono_class_get_type(monoClass);
  148. int monoPrimitiveType = mono_type_get_type(monoType);
  149. switch(monoPrimitiveType)
  150. {
  151. case MONO_TYPE_BOOLEAN:
  152. return MonoPrimitiveType::Boolean;
  153. case MONO_TYPE_CHAR:
  154. return MonoPrimitiveType::Char;
  155. case MONO_TYPE_I1:
  156. return MonoPrimitiveType::I8;
  157. case MONO_TYPE_U1:
  158. return MonoPrimitiveType::U8;
  159. case MONO_TYPE_I2:
  160. return MonoPrimitiveType::I16;
  161. case MONO_TYPE_U2:
  162. return MonoPrimitiveType::U16;
  163. case MONO_TYPE_I4:
  164. return MonoPrimitiveType::I32;
  165. case MONO_TYPE_U4:
  166. return MonoPrimitiveType::U32;
  167. case MONO_TYPE_I8:
  168. return MonoPrimitiveType::I64;
  169. case MONO_TYPE_U8:
  170. return MonoPrimitiveType::U64;
  171. case MONO_TYPE_R4:
  172. return MonoPrimitiveType::R32;
  173. case MONO_TYPE_R8:
  174. return MonoPrimitiveType::R64;
  175. case MONO_TYPE_STRING:
  176. return MonoPrimitiveType::String;
  177. case MONO_TYPE_CLASS:
  178. return MonoPrimitiveType::Class;
  179. case MONO_TYPE_VALUETYPE:
  180. return MonoPrimitiveType::ValueType;
  181. case MONO_TYPE_ARRAY:
  182. case MONO_TYPE_SZARRAY:
  183. return MonoPrimitiveType::Array;
  184. case MONO_TYPE_GENERICINST:
  185. return MonoPrimitiveType::Generic;
  186. default:
  187. break;
  188. }
  189. return MonoPrimitiveType::Unknown;
  190. }
  191. ::MonoClass* MonoUtil::bindGenericParameters(::MonoClass* klass, ::MonoClass** params, UINT32 numParams)
  192. {
  193. MonoType** types = (MonoType**)bs_alloc(sizeof(MonoType*) * numParams);
  194. for (UINT32 i = 0; i < numParams; i++)
  195. types[i] = mono_class_get_type(params[i]);
  196. return mono_class_bind_generic_parameters(klass, numParams, types, false);
  197. }
  198. ::MonoClass* MonoUtil::getUINT16Class()
  199. {
  200. return mono_get_uint16_class();
  201. }
  202. ::MonoClass* MonoUtil::getINT16Class()
  203. {
  204. return mono_get_int16_class();
  205. }
  206. ::MonoClass* MonoUtil::getUINT32Class()
  207. {
  208. return mono_get_uint32_class();
  209. }
  210. ::MonoClass* MonoUtil::getINT32Class()
  211. {
  212. return mono_get_int32_class();
  213. }
  214. ::MonoClass* MonoUtil::getUINT64Class()
  215. {
  216. return mono_get_uint64_class();
  217. }
  218. ::MonoClass* MonoUtil::getINT64Class()
  219. {
  220. return mono_get_int64_class();
  221. }
  222. ::MonoClass* MonoUtil::getStringClass()
  223. {
  224. return mono_get_string_class();
  225. }
  226. ::MonoClass* MonoUtil::getFloatClass()
  227. {
  228. return mono_get_single_class();
  229. }
  230. ::MonoClass* MonoUtil::getDoubleClass()
  231. {
  232. return mono_get_double_class();
  233. }
  234. ::MonoClass* MonoUtil::getBoolClass()
  235. {
  236. return mono_get_boolean_class();
  237. }
  238. ::MonoClass* MonoUtil::getByteClass()
  239. {
  240. return mono_get_byte_class();
  241. }
  242. ::MonoClass* MonoUtil::getSByteClass()
  243. {
  244. return mono_get_sbyte_class();
  245. }
  246. ::MonoClass* MonoUtil::getCharClass()
  247. {
  248. return mono_get_char_class();
  249. }
  250. ::MonoClass* MonoUtil::getObjectClass()
  251. {
  252. return mono_get_object_class();
  253. }
  254. void MonoUtil::throwIfException(MonoException* exception)
  255. {
  256. throwIfException(reinterpret_cast<MonoObject*>(exception));
  257. }
  258. void MonoUtil::throwIfException(MonoObject* exception)
  259. {
  260. if (exception != nullptr)
  261. {
  262. ::MonoClass* exceptionClass = mono_object_get_class(exception);
  263. ::MonoProperty* exceptionMsgProp = mono_class_get_property_from_name(exceptionClass, "Message");
  264. ::MonoMethod* exceptionMsgGetter = mono_property_get_get_method(exceptionMsgProp);
  265. MonoString* exceptionMsg = (MonoString*)mono_runtime_invoke(exceptionMsgGetter, exception, nullptr, nullptr);
  266. ::MonoProperty* exceptionStackProp = mono_class_get_property_from_name(exceptionClass, "StackTrace");
  267. ::MonoMethod* exceptionStackGetter = mono_property_get_get_method(exceptionStackProp);
  268. MonoString* exceptionStackTrace = (MonoString*)mono_runtime_invoke(exceptionStackGetter, exception, nullptr, nullptr);
  269. // Note: If you modify this format make sure to also modify Debug.ParseExceptionMessage in managed code.
  270. String msg = "Managed exception: " + toString(monoToWString(exceptionMsg)) + "\n" + toString(monoToWString(exceptionStackTrace));
  271. LOGERR(msg);
  272. }
  273. }
  274. }