BsMonoUtil.cpp 8.1 KB

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