NETCore.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. #include <Atomic/Core/StringUtils.h>
  2. #include <Atomic/Core/CoreEvents.h>
  3. #include <Atomic/IO/FileSystem.h>
  4. #include <Atomic/IO/Log.h>
  5. #include <Atomic/Resource/ResourceCache.h>
  6. #include "CSEventHelper.h"
  7. #include "CSComponent.h"
  8. #include "NETCore.h"
  9. #include "NETManaged.h"
  10. #include "NETAssemblyFile.h"
  11. #ifdef ATOMIC_PLATFORM_WINDOWS
  12. #include "Platforms/Windows/NETHostWindows.h"
  13. #else
  14. #include "Platforms/Unix/NETHostUnix.h"
  15. #endif
  16. namespace Atomic
  17. {
  18. /// Register NETCore library objects.
  19. void ATOMIC_API RegisterNETCoreLibrary(Context* context);
  20. WeakPtr<Context> NETCore::csContext_;
  21. WeakPtr<NETCore> NETCore::instance_;
  22. NETCore::NETCore(Context* context) :
  23. Object(context)
  24. {
  25. RegisterNETCoreLibrary(context_);
  26. assert(!instance_);
  27. instance_ = this;
  28. csContext_ = context;
  29. }
  30. NETCore::~NETCore()
  31. {
  32. Shutdown();
  33. context_->RemoveGlobalEventListener(context_->GetSubsystem<CSEventDispatcher>());
  34. context_->RemoveSubsystem(CSEventDispatcher::GetTypeStatic());
  35. context_->RemoveSubsystem(NETManaged::GetTypeStatic());
  36. instance_ = NULL;
  37. }
  38. void NETCore::Shutdown()
  39. {
  40. RefCounted::SetRefCountedDeletedFunction(0);
  41. if (netHost_.NotNull())
  42. {
  43. netHost_->Shutdown();
  44. netHost_ = 0;
  45. }
  46. }
  47. extern "C"
  48. {
  49. // http://ybeernet.blogspot.com/2011/03/techniques-of-calling-unmanaged-code.html
  50. // pinvoke is faster than [UnmanagedFunctionPointer] :/
  51. // [SuppressUnmanagedCodeSecurity] <--- add this attribute, in any event
  52. #ifdef ATOMIC_PLATFORM_WINDOWS
  53. #pragma warning(disable: 4244) // possible loss of data
  54. #define ATOMIC_EXPORT_API __declspec(dllexport)
  55. #else
  56. #define ATOMIC_EXPORT_API
  57. #endif
  58. ATOMIC_EXPORT_API ClassID csb_Atomic_RefCounted_GetClassID(RefCounted* refCounted)
  59. {
  60. if (!refCounted)
  61. return 0;
  62. return refCounted->GetClassID();
  63. }
  64. ATOMIC_EXPORT_API RefCounted* csb_AtomicEngine_GetSubsystem(const char* name)
  65. {
  66. return NETCore::GetContext()->GetSubsystem(name);
  67. }
  68. ATOMIC_EXPORT_API void csb_AtomicEngine_ReleaseRef(RefCounted* ref)
  69. {
  70. if (!ref)
  71. return;
  72. ref->ReleaseRef();
  73. }
  74. }
  75. void NETCore::WaitForDebuggerConnect()
  76. {
  77. netHost_->WaitForDebuggerConnect();
  78. }
  79. void NETCore::AddAssemblyLoadPath(const String& assemblyPath)
  80. {
  81. typedef void (*AddAssemblyLoadPathFunction)(const char* assemblyPath);
  82. AddAssemblyLoadPathFunction addAssemblyLoadPath;
  83. bool result = CreateDelegate(
  84. "AtomicNETBootstrap",
  85. "Atomic.Bootstrap.AtomicLoadContext",
  86. "AddAssemblyLoadPath",
  87. (void**) &addAssemblyLoadPath);
  88. if (result)
  89. {
  90. addAssemblyLoadPath(assemblyPath.CString());
  91. }
  92. }
  93. bool NETCore::CreateDelegate(const String& assemblyName, const String& qualifiedClassName, const String& methodName, void** funcOut)
  94. {
  95. return netHost_->CreateDelegate(assemblyName, qualifiedClassName, methodName, funcOut);
  96. }
  97. bool NETCore::Start()
  98. {
  99. if (context_->GetEditorContext())
  100. return true;
  101. typedef void (*StartFunction)();
  102. StartFunction start;
  103. bool result = netHost_->CreateDelegate(
  104. "AtomicNETEngine",
  105. "AtomicEngine.Atomic",
  106. "Start",
  107. (void**) &start);
  108. if (!result)
  109. return false;
  110. if (result)
  111. {
  112. start();
  113. // Load Project Assemblies
  114. typedef void (*ExecMainAssemblyFunction)();
  115. ExecMainAssemblyFunction execMainAssembly;
  116. result = netHost_->CreateDelegate(
  117. "AtomicNETEngine",
  118. "AtomicEngine.Atomic",
  119. "ExecMainAssembly",
  120. (void**) &execMainAssembly);
  121. if (!result)
  122. return false;
  123. execMainAssembly();
  124. }
  125. return true;
  126. }
  127. bool NETCore::Initialize(String& errorMsg)
  128. {
  129. #ifdef ATOMIC_PLATFORM_WINDOWS
  130. netHost_ = new NETHostWindows(context_);
  131. #else
  132. netHost_ = new NETHostUnix(context_);
  133. #endif
  134. if (!netHost_->Initialize())
  135. {
  136. errorMsg = "NETHost Failed to Initialize";
  137. return false;
  138. }
  139. // MOVE THIS!
  140. typedef void (*StartupFunction)(const char* assemblyLoadPaths);
  141. StartupFunction startup;
  142. // The coreclr binding model will become locked upon loading the first assembly that is not on the TPA list, or
  143. // upon initializing the default context for the first time. For this test, test assemblies are located alongside
  144. // corerun, and hence will be on the TPA list. So, we should be able to set the default context once successfully,
  145. // and fail on the second try.
  146. // AssemblyLoadContext
  147. // https://github.com/dotnet/corefx/issues/3054
  148. // dnx loader
  149. // https://github.com/aspnet/dnx/tree/dev/src/Microsoft.Dnx.Loader
  150. bool result = netHost_->CreateDelegate(
  151. "AtomicNETBootstrap",
  152. "Atomic.Bootstrap.AtomicLoadContext",
  153. "Startup",
  154. (void**) &startup);
  155. if (result)
  156. {
  157. startup(netHost_->GetCoreCLRAssemblyLoadPaths().CString());
  158. }
  159. // MOVE THIS!
  160. typedef void (*InitializeFunction)();
  161. InitializeFunction init;
  162. result = netHost_->CreateDelegate(
  163. "AtomicNETEngine",
  164. "AtomicEngine.Atomic",
  165. "Initialize",
  166. (void**) &init);
  167. if (result)
  168. {
  169. init();
  170. }
  171. SharedPtr<NETManaged> managed(new NETManaged(context_));
  172. context_->RegisterSubsystem(managed);
  173. SharedPtr<CSEventDispatcher> dispatcher(new CSEventDispatcher(context_));
  174. context_->RegisterSubsystem(dispatcher);
  175. context_->AddGlobalEventListener(dispatcher);
  176. if (!context_->GetEditorContext())
  177. {
  178. SubscribeToEvent(E_UPDATE, HANDLER(NETCore, HandleUpdate));
  179. }
  180. return managed->Initialize();
  181. }
  182. void NETCore::HandleUpdate(StringHash eventType, VariantMap& eventData)
  183. {
  184. using namespace Update;
  185. GetSubsystem<NETManaged>()->NETUpdate(eventData[P_TIMESTEP].GetFloat());
  186. }
  187. void RegisterNETCoreLibrary(Context* context)
  188. {
  189. NETAssemblyFile::RegisterObject(context);
  190. CSComponent::RegisterObject(context);
  191. }
  192. }