BsMonoManager.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #include "BsMonoManager.h"
  2. #include "CmException.h"
  3. #include "BsScriptMeta.h"
  4. #include "BsMonoAssembly.h"
  5. #include "BsMonoClass.h"
  6. #include <mono/metadata/assembly.h>
  7. #include <mono/metadata/mono-config.h>
  8. namespace BansheeEngine
  9. {
  10. const String MonoManager::MONO_LIB_DIR = "..\\..\\Mono\\lib";
  11. const String MonoManager::MONO_ETC_DIR = "..\\..\\Mono\\etc";
  12. MonoManager::MonoManager()
  13. :mDomain(nullptr), mIsCoreLoaded(false)
  14. {
  15. mono_set_dirs(MONO_LIB_DIR.c_str(), MONO_ETC_DIR.c_str());
  16. mono_config_parse(nullptr);
  17. }
  18. MonoManager::~MonoManager()
  19. {
  20. if(mDomain != nullptr)
  21. {
  22. mono_jit_cleanup(mDomain);
  23. mDomain = nullptr;
  24. }
  25. for (auto& entry : mAssemblies)
  26. {
  27. unloadAssembly(*entry.second);
  28. cm_delete(entry.second);
  29. }
  30. mAssemblies.clear();
  31. }
  32. MonoAssembly& MonoManager::loadAssembly(const String& path, const String& name)
  33. {
  34. MonoAssembly* assembly = nullptr;
  35. if(mDomain == nullptr)
  36. {
  37. mDomain = mono_jit_init (path.c_str());
  38. if(mDomain == nullptr)
  39. {
  40. CM_EXCEPT(InternalErrorException, "Cannot initialize Mono runtime.");
  41. }
  42. }
  43. auto iterFind = mAssemblies.find(name);
  44. if(iterFind != mAssemblies.end())
  45. {
  46. assembly = iterFind->second;
  47. }
  48. else
  49. {
  50. assembly = new (cm_alloc<MonoAssembly>()) MonoAssembly();
  51. mAssemblies[name] = assembly;
  52. }
  53. if(!assembly->mIsLoaded)
  54. {
  55. assembly->load(path, name);
  56. // Fully initialize all types that use this assembly
  57. Vector<ScriptMeta*>& mTypeMetas = getTypesToInitialize()[name];
  58. for(auto& meta : mTypeMetas)
  59. {
  60. meta->scriptClass = assembly->getClass(meta->ns, meta->name);
  61. if(meta->scriptClass == nullptr)
  62. CM_EXCEPT(InvalidParametersException, "Unable to find class of type: \"" + meta->ns + "::" + meta->name + "\"");
  63. if(meta->scriptClass->hasField("mCachedPtr"))
  64. meta->thisPtrField = meta->scriptClass->getField("mCachedPtr");
  65. else
  66. meta->thisPtrField = nullptr;
  67. meta->initCallback();
  68. }
  69. }
  70. if(!mIsCoreLoaded)
  71. {
  72. mIsCoreLoaded = true;
  73. MonoImage* existingImage = mono_image_loaded("mscorlib");
  74. if(existingImage != nullptr)
  75. {
  76. MonoAssembly* mscorlib = new (cm_alloc<MonoAssembly>()) MonoAssembly();
  77. mAssemblies["mscorlib"] = mscorlib;
  78. mscorlib->loadAsDependency(existingImage, "mscorlib");
  79. }
  80. else
  81. loadAssembly("mscorlib", "mscorlib");
  82. }
  83. return *assembly;
  84. }
  85. void MonoManager::unloadAssembly(MonoAssembly& assembly)
  86. {
  87. ::MonoAssembly* monoAssembly = assembly.mMonoAssembly;
  88. assembly.unload();
  89. // TODO: Not calling this because it crashed if called before domain was unloaded. Try calling
  90. // it after. I'm not sure if its even necessary to call it.
  91. //if(monoAssembly)
  92. //mono_assembly_close(monoAssembly);
  93. }
  94. MonoAssembly* MonoManager::getAssembly(const String& name) const
  95. {
  96. auto iterFind = mAssemblies.find(name);
  97. if(iterFind != mAssemblies.end())
  98. return iterFind->second;
  99. return nullptr;
  100. }
  101. void MonoManager::registerScriptType(ScriptMeta* metaData)
  102. {
  103. Vector<ScriptMeta*>& mMetas = getTypesToInitialize()[metaData->assembly];
  104. mMetas.push_back(metaData);
  105. }
  106. MonoClass* MonoManager::findClass(const String& ns, const String& typeName)
  107. {
  108. MonoClass* monoClass = nullptr;
  109. for(auto& assembly : mAssemblies)
  110. {
  111. monoClass = assembly.second->getClass(ns, typeName);
  112. if(monoClass != nullptr)
  113. return monoClass;
  114. }
  115. return nullptr;
  116. }
  117. MonoClass* MonoManager::findClass(::MonoClass* rawMonoClass)
  118. {
  119. MonoClass* monoClass = nullptr;
  120. for(auto& assembly : mAssemblies)
  121. {
  122. monoClass = assembly.second->getClass(rawMonoClass);
  123. if(monoClass != nullptr)
  124. return monoClass;
  125. }
  126. return nullptr;
  127. }
  128. String MonoManager::getFullTypeName(MonoObject* obj)
  129. {
  130. if(obj == nullptr)
  131. CM_EXCEPT(InvalidParametersException, "Object cannot be null.");
  132. ::MonoClass* monoClass = mono_object_get_class(obj);
  133. const char* nameSpaceChars = mono_class_get_namespace(monoClass);
  134. String namespaceStr;
  135. if(nameSpaceChars != nullptr)
  136. namespaceStr = nameSpaceChars;
  137. const char* typeNameChars = mono_class_get_name(monoClass);
  138. String typeNameStr;
  139. if(typeNameChars != nullptr)
  140. typeNameStr = typeNameChars;
  141. return namespaceStr + "." + typeNameStr;
  142. }
  143. String MonoManager::getNamespace(MonoObject* obj)
  144. {
  145. if(obj == nullptr)
  146. CM_EXCEPT(InvalidParametersException, "Object cannot be null.");
  147. ::MonoClass* monoClass = mono_object_get_class(obj);
  148. const char* nameSpaceChars = mono_class_get_namespace(monoClass);
  149. String namespaceStr;
  150. if(nameSpaceChars != nullptr)
  151. namespaceStr = nameSpaceChars;
  152. return namespaceStr;
  153. }
  154. String MonoManager::getTypeName(MonoObject* obj)
  155. {
  156. if(obj == nullptr)
  157. CM_EXCEPT(InvalidParametersException, "Object cannot be null.");
  158. ::MonoClass* monoClass = mono_object_get_class(obj);
  159. const char* typeNameChars = mono_class_get_name(monoClass);
  160. String typeNameStr;
  161. if(typeNameChars != nullptr)
  162. typeNameStr = typeNameChars;
  163. return typeNameStr;
  164. }
  165. }