BsMonoManager.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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. using namespace CamelotFramework;
  9. namespace BansheeEngine
  10. {
  11. const String MonoManager::MONO_LIB_DIR = "..\\..\\Mono\\lib";
  12. const String MonoManager::MONO_ETC_DIR = "..\\..\\Mono\\etc";
  13. MonoManager::MonoManager()
  14. :mDomain(nullptr)
  15. {
  16. mono_set_dirs(MONO_LIB_DIR.c_str(), MONO_ETC_DIR.c_str());
  17. mono_config_parse(nullptr);
  18. }
  19. MonoManager::~MonoManager()
  20. {
  21. for(auto& entry : mAssemblies)
  22. {
  23. unloadAssembly(*entry.second);
  24. cm_delete(entry.second);
  25. }
  26. mAssemblies.clear();
  27. if(mDomain != nullptr)
  28. {
  29. mono_jit_cleanup(mDomain);
  30. mDomain = nullptr;
  31. }
  32. }
  33. MonoAssembly& MonoManager::loadAssembly(const String& path, const String& name, const String& entryPoint)
  34. {
  35. MonoAssembly* assembly = nullptr;
  36. if(mDomain == nullptr)
  37. {
  38. mDomain = mono_jit_init (path.c_str());
  39. if(mDomain == nullptr)
  40. {
  41. CM_EXCEPT(InternalErrorException, "Cannot initialize Mono runtime.");
  42. }
  43. }
  44. auto iterFind = mAssemblies.find(name);
  45. if(iterFind != mAssemblies.end())
  46. {
  47. assembly = iterFind->second;
  48. }
  49. else
  50. {
  51. assembly = new (cm_alloc<MonoAssembly>()) MonoAssembly();
  52. mAssemblies[name] = assembly;
  53. }
  54. if(!assembly->mIsLoaded)
  55. {
  56. assembly->load(path, name);
  57. // Fully initialize all types that use this assembly
  58. Vector<ScriptMeta*>::type& mTypeMetas = getTypesToInitialize()[name];
  59. for(auto& meta : mTypeMetas)
  60. {
  61. meta->scriptClass = assembly->getClass(meta->ns, meta->name);
  62. if(meta->scriptClass == nullptr)
  63. CM_EXCEPT(InvalidParametersException, "Unable to find class of type: \"" + meta->ns + "::" + meta->name + "\"");
  64. if(meta->scriptClass->hasField("mCachedPtr"))
  65. meta->thisPtrField = &meta->scriptClass->getField("mCachedPtr");
  66. else
  67. meta->thisPtrField = nullptr;
  68. meta->initCallback();
  69. }
  70. assembly->initialize(entryPoint); // Perform any initialization after everything is loaded
  71. }
  72. return *assembly;
  73. }
  74. void MonoManager::unloadAssembly(MonoAssembly& assembly)
  75. {
  76. ::MonoAssembly* monoAssembly = assembly.mMonoAssembly;
  77. assembly.unload();
  78. if(monoAssembly)
  79. mono_assembly_close(monoAssembly);
  80. }
  81. MonoAssembly* MonoManager::getAssembly(const CM::String& name) const
  82. {
  83. auto iterFind = mAssemblies.find(name);
  84. if(iterFind != mAssemblies.end())
  85. return iterFind->second;
  86. return nullptr;
  87. }
  88. void MonoManager::registerScriptType(ScriptMeta* metaData)
  89. {
  90. Vector<ScriptMeta*>::type& mMetas = getTypesToInitialize()[metaData->assembly];
  91. mMetas.push_back(metaData);
  92. }
  93. MonoClass* MonoManager::findClass(const CM::String& ns, const CM::String& typeName)
  94. {
  95. MonoClass* monoClass = nullptr;
  96. for(auto& assembly : mAssemblies)
  97. {
  98. monoClass = assembly.second->getClass(ns, typeName);
  99. if(monoClass != nullptr)
  100. return monoClass;
  101. }
  102. return nullptr;
  103. }
  104. String MonoManager::getFullTypeName(MonoObject* obj)
  105. {
  106. if(obj == nullptr)
  107. CM_EXCEPT(InvalidParametersException, "Object cannot be null.");
  108. ::MonoClass* monoClass = mono_object_get_class(obj);
  109. const char* nameSpaceChars = mono_class_get_namespace(monoClass);
  110. String namespaceStr;
  111. if(nameSpaceChars != nullptr)
  112. namespaceStr = nameSpaceChars;
  113. const char* typeNameChars = mono_class_get_name(monoClass);
  114. String typeNameStr;
  115. if(typeNameChars != nullptr)
  116. typeNameStr = typeNameChars;
  117. return namespaceStr + "." + typeNameStr;
  118. }
  119. String MonoManager::getNamespace(MonoObject* obj)
  120. {
  121. if(obj == nullptr)
  122. CM_EXCEPT(InvalidParametersException, "Object cannot be null.");
  123. ::MonoClass* monoClass = mono_object_get_class(obj);
  124. const char* nameSpaceChars = mono_class_get_namespace(monoClass);
  125. String namespaceStr;
  126. if(nameSpaceChars != nullptr)
  127. namespaceStr = nameSpaceChars;
  128. return namespaceStr;
  129. }
  130. String MonoManager::getTypeName(MonoObject* obj)
  131. {
  132. if(obj == nullptr)
  133. CM_EXCEPT(InvalidParametersException, "Object cannot be null.");
  134. ::MonoClass* monoClass = mono_object_get_class(obj);
  135. const char* typeNameChars = mono_class_get_name(monoClass);
  136. String typeNameStr;
  137. if(typeNameChars != nullptr)
  138. typeNameStr = typeNameChars;
  139. return typeNameStr;
  140. }
  141. }