BsMonoManager.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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. for(auto& entry : mAssemblies)
  21. {
  22. unloadAssembly(*entry.second);
  23. cm_delete(entry.second);
  24. }
  25. mAssemblies.clear();
  26. if(mDomain != nullptr)
  27. {
  28. mono_jit_cleanup(mDomain);
  29. mDomain = nullptr;
  30. }
  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*>::type& 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. if(monoAssembly)
  90. mono_assembly_close(monoAssembly);
  91. }
  92. MonoAssembly* MonoManager::getAssembly(const String& name) const
  93. {
  94. auto iterFind = mAssemblies.find(name);
  95. if(iterFind != mAssemblies.end())
  96. return iterFind->second;
  97. return nullptr;
  98. }
  99. void MonoManager::registerScriptType(ScriptMeta* metaData)
  100. {
  101. Vector<ScriptMeta*>::type& mMetas = getTypesToInitialize()[metaData->assembly];
  102. mMetas.push_back(metaData);
  103. }
  104. MonoClass* MonoManager::findClass(const String& ns, const String& typeName)
  105. {
  106. MonoClass* monoClass = nullptr;
  107. for(auto& assembly : mAssemblies)
  108. {
  109. monoClass = assembly.second->getClass(ns, typeName);
  110. if(monoClass != nullptr)
  111. return monoClass;
  112. }
  113. return nullptr;
  114. }
  115. MonoClass* MonoManager::findClass(::MonoClass* rawMonoClass)
  116. {
  117. MonoClass* monoClass = nullptr;
  118. for(auto& assembly : mAssemblies)
  119. {
  120. monoClass = assembly.second->getClass(rawMonoClass);
  121. if(monoClass != nullptr)
  122. return monoClass;
  123. }
  124. return nullptr;
  125. }
  126. String MonoManager::getFullTypeName(MonoObject* obj)
  127. {
  128. if(obj == nullptr)
  129. CM_EXCEPT(InvalidParametersException, "Object cannot be null.");
  130. ::MonoClass* monoClass = mono_object_get_class(obj);
  131. const char* nameSpaceChars = mono_class_get_namespace(monoClass);
  132. String namespaceStr;
  133. if(nameSpaceChars != nullptr)
  134. namespaceStr = nameSpaceChars;
  135. const char* typeNameChars = mono_class_get_name(monoClass);
  136. String typeNameStr;
  137. if(typeNameChars != nullptr)
  138. typeNameStr = typeNameChars;
  139. return namespaceStr + "." + typeNameStr;
  140. }
  141. String MonoManager::getNamespace(MonoObject* obj)
  142. {
  143. if(obj == nullptr)
  144. CM_EXCEPT(InvalidParametersException, "Object cannot be null.");
  145. ::MonoClass* monoClass = mono_object_get_class(obj);
  146. const char* nameSpaceChars = mono_class_get_namespace(monoClass);
  147. String namespaceStr;
  148. if(nameSpaceChars != nullptr)
  149. namespaceStr = nameSpaceChars;
  150. return namespaceStr;
  151. }
  152. String MonoManager::getTypeName(MonoObject* obj)
  153. {
  154. if(obj == nullptr)
  155. CM_EXCEPT(InvalidParametersException, "Object cannot be null.");
  156. ::MonoClass* monoClass = mono_object_get_class(obj);
  157. const char* typeNameChars = mono_class_get_name(monoClass);
  158. String typeNameStr;
  159. if(typeNameChars != nullptr)
  160. typeNameStr = typeNameChars;
  161. return typeNameStr;
  162. }
  163. }