BsMonoAssembly.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #include "BsMonoAssembly.h"
  2. #include "BsMonoClass.h"
  3. #include "BsMonoManager.h"
  4. #include "CmUtil.h"
  5. #include "CmException.h"
  6. #include <mono/metadata/debug-helpers.h>
  7. using namespace CamelotFramework;
  8. namespace BansheeEngine
  9. {
  10. inline size_t MonoAssembly::ClassId::Hash::operator()(const MonoAssembly::ClassId& v) const
  11. {
  12. size_t seed = 0;
  13. hash_combine(seed, v.namespaceName);
  14. hash_combine(seed, v.name);
  15. return seed;
  16. }
  17. inline bool MonoAssembly::ClassId::Equals::operator()(const MonoAssembly::ClassId& a, const MonoAssembly::ClassId& b) const
  18. {
  19. return a.name == b.name && a.namespaceName == b.namespaceName;
  20. }
  21. MonoAssembly::ClassId::ClassId(const String& namespaceName, String name)
  22. :namespaceName(namespaceName), name(name)
  23. {
  24. }
  25. MonoAssembly::MonoAssembly()
  26. :mIsLoaded(false), mMonoImage(nullptr), mMonoAssembly(nullptr), mDomain(nullptr)
  27. {
  28. }
  29. MonoAssembly::~MonoAssembly()
  30. {
  31. unload();
  32. if(mDomain != nullptr)
  33. {
  34. mono_jit_cleanup(mDomain);
  35. mDomain = nullptr;
  36. }
  37. }
  38. void MonoAssembly::load(const CM::String& path, const CM::String& name)
  39. {
  40. if(mDomain == nullptr)
  41. {
  42. mDomain = mono_jit_init (path.c_str());
  43. if(mDomain == nullptr)
  44. {
  45. CM_EXCEPT(InternalErrorException, "Cannot initialize Mono runtime.");
  46. }
  47. }
  48. ::MonoAssembly* monoAssembly = mono_domain_assembly_open (mDomain, path.c_str());
  49. if(monoAssembly == nullptr)
  50. {
  51. CM_EXCEPT(InvalidParametersException, "Cannot load Mono assembly: " + path);
  52. }
  53. mName = name;
  54. mMonoAssembly = monoAssembly;
  55. mMonoImage = mono_assembly_get_image(mMonoAssembly);
  56. if(mMonoImage == nullptr)
  57. {
  58. CM_EXCEPT(InvalidParametersException, "Cannot get script assembly image.");
  59. }
  60. mIsLoaded = true;
  61. }
  62. void MonoAssembly::unload()
  63. {
  64. if(!mIsLoaded)
  65. return;
  66. for(auto& entry : mClasses)
  67. cm_delete(entry.second);
  68. mClasses.clear();
  69. if(mMonoImage != nullptr)
  70. {
  71. mono_image_close(mMonoImage);
  72. mMonoImage = nullptr;
  73. }
  74. mIsLoaded = false;
  75. mMonoAssembly = nullptr;
  76. }
  77. void MonoAssembly::initialize(const CM::String& entryPoint)
  78. {
  79. MonoMethodDesc* methodDesc = mono_method_desc_new(entryPoint.c_str(), false);
  80. ::MonoMethod* entry = mono_method_desc_search_in_image(methodDesc, mMonoImage);
  81. if(entry != nullptr)
  82. mono_runtime_invoke(entry, nullptr, nullptr, nullptr);
  83. }
  84. MonoClass& MonoAssembly::getClass(const String& namespaceName, const String& name)
  85. {
  86. if(!mIsLoaded)
  87. CM_EXCEPT(InvalidStateException, "Trying to use an unloaded assembly.");
  88. ClassId classId(namespaceName, name);
  89. auto iterFind = mClasses.find(classId);
  90. if(iterFind != mClasses.end())
  91. return *iterFind->second;
  92. ::MonoClass* monoClass = mono_class_from_name(mMonoImage, namespaceName.c_str(), name.c_str());
  93. if(monoClass == nullptr)
  94. {
  95. CM_EXCEPT(InvalidParametersException, "Cannot get Mono class: " + namespaceName + "." + name);
  96. }
  97. String fullClassName = namespaceName + "." + name;
  98. MonoClass* newClass = new (cm_alloc<MonoClass>()) MonoClass(fullClassName, monoClass, this);
  99. mClasses[classId] = newClass;
  100. return *newClass;
  101. }
  102. }