NETCore.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. #include <ThirdParty/SDL/include/SDL.h>
  2. #include <Atomic/IO/FileSystem.h>
  3. #include <Atomic/IO/Log.h>
  4. #include <Atomic/Core/StringUtils.h>
  5. #include "CSEventHelper.h"
  6. #include "CSComponent.h"
  7. #include "NETCore.h"
  8. #include "NETManaged.h"
  9. #include "NETCoreThunk.h"
  10. namespace Atomic
  11. {
  12. /*
  13. mcs /nostdlib /noconfig /r:System.Console.dll /r:System.Runtime.dll /r:System.IO.dll /r:System.IO.FileSystem.dll /r:mscorlib.dll HelloWorld.cs
  14. */
  15. #ifdef ATOMIC_PLATFORM_OSX
  16. static const char * const sCoreClrDll = "libcoreclr.dylib";
  17. #else
  18. static const char * const sCoreClrDll = "libcoreclr.so";
  19. #endif
  20. // Prototype of the coreclr_initialize function from the libcoreclr.so
  21. typedef int (*InitializeCoreCLRFunction)(
  22. const char* exePath,
  23. const char* appDomainFriendlyName,
  24. int propertyCount,
  25. const char** propertyKeys,
  26. const char** propertyValues,
  27. void** hostHandle,
  28. unsigned int* domainId);
  29. // Prototype of the coreclr_shutdown function from the libcoreclr.so
  30. typedef int (*ShutdownCoreCLRFunction)(
  31. void* hostHandle,
  32. unsigned int domainId);
  33. // Prototype of the coreclr_execute_assembly function from the libcoreclr.so
  34. typedef int (*ExecuteAssemblyFunction)(
  35. void* hostHandle,
  36. unsigned int domainId,
  37. int argc,
  38. const char** argv,
  39. const char* managedAssemblyPath,
  40. unsigned int* exitCode);
  41. typedef int (*CreateDelegateFunction)(
  42. void* hostHandle,
  43. unsigned int domainId,
  44. const char* entryPointAssemblyName,
  45. const char* entryPointTypeName,
  46. const char* entryPointMethodName,
  47. void** delegate);
  48. static InitializeCoreCLRFunction sInitializeCoreCLR = 0;
  49. static ExecuteAssemblyFunction sExecuteAssembly = 0;
  50. static CreateDelegateFunction sCreateDelegate = 0;
  51. static ShutdownCoreCLRFunction sShutdownCoreCLR = 0;
  52. /// Register NETCore library objects.
  53. void ATOMIC_API RegisterNETCoreLibrary(Context* context);
  54. WeakPtr<Context> NETCore::csContext_;
  55. WeakPtr<NETCore> NETCore::instance_;
  56. NETCore::NETCore(Context* context) :
  57. Object(context),
  58. coreCLRDLLHandle_(0),
  59. hostHandle_(0),
  60. domainId_(0)
  61. {
  62. RegisterNETCoreLibrary(context_);
  63. NetCoreThunkInit();
  64. assert(!instance_);
  65. instance_ = this;
  66. csContext_ = context;
  67. SharedPtr<NETManaged> managed(new NETManaged(context_));
  68. context_->RegisterSubsystem(managed);
  69. SharedPtr<CSEventDispatcher> dispatcher(new CSEventDispatcher(context_));
  70. context_->RegisterSubsystem(dispatcher);
  71. context_->AddGlobalEventListener(dispatcher);
  72. }
  73. NETCore::~NETCore()
  74. {
  75. context_->RemoveGlobalEventListener(context_->GetSubsystem<CSEventDispatcher>());
  76. context_->RemoveSubsystem(CSEventDispatcher::GetTypeStatic());
  77. context_->RemoveSubsystem(NETManaged::GetTypeStatic());
  78. instance_ = NULL;
  79. }
  80. void NETCore::GenerateTPAList(String& tpaList)
  81. {
  82. tpaList = String::EMPTY;
  83. FileSystem* fs = GetSubsystem<FileSystem>();
  84. Vector<String> results;
  85. fs->ScanDir(results, coreCLRFilesAbsPath_, "*.dll", SCAN_FILES, true);
  86. Vector<String> trustedAssemblies;
  87. for (unsigned i = 0; i < results.Size(); i++)
  88. {
  89. const String& assembly = results[i];
  90. // TODO: apply filtering if necessary
  91. trustedAssemblies.Push(coreCLRFilesAbsPath_ + assembly);
  92. }
  93. tpaList.Join(trustedAssemblies, ":");
  94. // LOGINFOF("NetCore:: TPALIST - %s", tpaList.CString());
  95. }
  96. void NETCore::Shutdown()
  97. {
  98. if (sShutdownCoreCLR && hostHandle_)
  99. {
  100. sShutdownCoreCLR(hostHandle_, domainId_);
  101. }
  102. if (coreCLRDLLHandle_)
  103. {
  104. SDL_UnloadObject(coreCLRDLLHandle_);
  105. }
  106. coreCLRDLLHandle_ = 0;
  107. hostHandle_ = 0;
  108. domainId_ = 0;
  109. sInitializeCoreCLR = 0;
  110. sExecuteAssembly = 0;
  111. sCreateDelegate = 0;
  112. sShutdownCoreCLR = 0;
  113. }
  114. bool NETCore::InitCoreCLRDLL(String& errorMsg)
  115. {
  116. String coreClrDllPath = AddTrailingSlash(coreCLRFilesAbsPath_) + sCoreClrDll;
  117. coreCLRDLLHandle_ = SDL_LoadObject(coreClrDllPath.CString());
  118. if (coreCLRDLLHandle_ == NULL)
  119. {
  120. errorMsg = ToString("NETCore: Unable to load %s with error %s",
  121. coreClrDllPath.CString(),
  122. SDL_GetError());
  123. return false;
  124. }
  125. sInitializeCoreCLR = (InitializeCoreCLRFunction) SDL_LoadFunction(coreCLRDLLHandle_, "coreclr_initialize");
  126. if (!sInitializeCoreCLR)
  127. {
  128. errorMsg = ToString("NETCore: Unable to get coreclr_initialize entry point in %s", coreClrDllPath.CString());
  129. return false;
  130. }
  131. sShutdownCoreCLR = (ShutdownCoreCLRFunction) SDL_LoadFunction(coreCLRDLLHandle_, "coreclr_shutdown");
  132. if (!sShutdownCoreCLR)
  133. {
  134. errorMsg = ToString("NETCore: Unable to get coreclr_shutdown entry point in %s", coreClrDllPath.CString());
  135. return false;
  136. }
  137. sCreateDelegate = (CreateDelegateFunction) SDL_LoadFunction(coreCLRDLLHandle_, "coreclr_create_delegate");
  138. if (!sCreateDelegate)
  139. {
  140. errorMsg = ToString("NETCore: Unable to get coreclr_create_delegate entry point in %s", coreClrDllPath.CString());
  141. return false;
  142. }
  143. sExecuteAssembly = (ExecuteAssemblyFunction) SDL_LoadFunction(coreCLRDLLHandle_, "coreclr_execute_assembly");
  144. if (!sExecuteAssembly)
  145. {
  146. errorMsg = ToString("NETCore: Unable to get coreclr_execute_assembly entry point in %s", coreClrDllPath.CString());
  147. return false;
  148. }
  149. return true;
  150. }
  151. extern "C"
  152. {
  153. // http://ybeernet.blogspot.com/2011/03/techniques-of-calling-unmanaged-code.html
  154. // pinvoke is faster than [UnmanagedFunctionPointer] :/
  155. // [SuppressUnmanagedCodeSecurity] <--- add this attribute, in any event
  156. void csb_Atomic_Test(unsigned id)
  157. {
  158. LOGINFOF("%u", id);
  159. }
  160. }
  161. bool NETCore::Initialize(const String &coreCLRFilesAbsPath, String& errorMsg)
  162. {
  163. coreCLRFilesAbsPath_ = AddTrailingSlash(coreCLRFilesAbsPath);
  164. if (!InitCoreCLRDLL(errorMsg))
  165. {
  166. Shutdown();
  167. return false;
  168. }
  169. // Allowed property names:
  170. // APPBASE
  171. // - The base path of the application from which the exe and other assemblies will be loaded
  172. //
  173. // TRUSTED_PLATFORM_ASSEMBLIES
  174. // - The list of complete paths to each of the fully trusted assemblies
  175. //
  176. // APP_PATHS
  177. // - The list of paths which will be probed by the assembly loader
  178. //
  179. // APP_NI_PATHS
  180. // - The list of additional paths that the assembly loader will probe for ngen images
  181. //
  182. // NATIVE_DLL_SEARCH_DIRECTORIES
  183. // - The list of paths that will be probed for native DLLs called by PInvoke
  184. //
  185. const char *propertyKeys[] = {
  186. "TRUSTED_PLATFORM_ASSEMBLIES",
  187. "APP_PATHS",
  188. "APP_NI_PATHS",
  189. "NATIVE_DLL_SEARCH_DIRECTORIES",
  190. "AppDomainCompatSwitch"
  191. };
  192. String tpaList;
  193. GenerateTPAList(tpaList);
  194. String appPath = "/Users/josh/Desktop/OSX.x64.Debug/";
  195. Vector<String> nativeSearch;
  196. nativeSearch.Push(coreCLRFilesAbsPath_);
  197. nativeSearch.Push("/Users/josh/Dev/atomic/AtomicGameEngineSharp-build/Source/AtomicNET/NETNative");
  198. String nativeDllSearchDirs;
  199. nativeDllSearchDirs.Join(nativeSearch, ":");
  200. const char *propertyValues[] = {
  201. // TRUSTED_PLATFORM_ASSEMBLIES
  202. tpaList.CString(),
  203. // APP_PATHS
  204. appPath.CString(),
  205. // APP_NI_PATHS
  206. appPath.CString(),
  207. // NATIVE_DLL_SEARCH_DIRECTORIES
  208. nativeDllSearchDirs.CString(),
  209. // AppDomainCompatSwitch
  210. "UseLatestBehaviorWhenTFMNotSpecified"
  211. };
  212. int st = sInitializeCoreCLR(
  213. "",
  214. "NETCore",
  215. sizeof(propertyKeys) / sizeof(propertyKeys[0]),
  216. propertyKeys,
  217. propertyValues,
  218. &hostHandle_,
  219. &domainId_);
  220. if (st < 0)
  221. {
  222. Shutdown();
  223. errorMsg = ToString("NETCore: coreclr_initialize failed - status: 0x%08x\n", st);
  224. return false;
  225. }
  226. /*
  227. void* hm;
  228. st = sCreateDelegate(hostHandle_,
  229. domainId_,
  230. "HelloWorld",
  231. "Hello1",
  232. "CallFromNative",
  233. &hm);
  234. if (st >= 0)
  235. {
  236. typedef void (*Hm)(const char* value);
  237. ((Hm)hm)("Hello From Native");
  238. }
  239. */
  240. /*
  241. unsigned int exitCode;
  242. st = sExecuteAssembly(
  243. hostHandle_,
  244. domainId_,
  245. 0,
  246. 0,
  247. "/Users/josh/Desktop/OSX.x64.Debug/HelloWorld.exe",
  248. (unsigned int*)&exitCode);
  249. */
  250. return true;
  251. }
  252. void RegisterNETCoreLibrary(Context* context)
  253. {
  254. CSComponent::RegisterObject(context);
  255. }
  256. }