summaryrefslogtreecommitdiff
path: root/Runtime/Mono/MonoManager.h
blob: b7c9b4b8c9618ec38d5fa6128f600b60b295a0d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#ifndef MONOMANAGER_H
#define MONOMANAGER_H

#include "MonoIncludes.h"
#include "Configuration/UnityConfigure.h"
#include "Runtime/Modules/ExportModules.h"

#if UNITY_FLASH
# include "Runtime/Scripting/MonoManager_Flash.h"
#elif UNITY_WINRT
# include "Runtime/Scripting/MonoManager_WinRT.h"
#endif

#if !ENABLE_MONO
struct MonoAssembly;
struct MonoVTable;
struct MonoException;
struct MonoClassField;
struct MonoDomain;
#endif

#if ENABLE_MONO

#include "Runtime/BaseClasses/GameManager.h"
#include <set>
#include <list>
#include "Runtime/Utilities/DateTime.h"
#include "Runtime/Utilities/dynamic_bitset.h"
#include "Runtime/Threads/ThreadSpecificValue.h"
#include "Runtime/Scripting/ScriptingUtility.h"
#include "Runtime/Scripting/Backend/ScriptingTypes.h"
#include "Runtime/Mono/MonoScriptManager.h"
#include "Runtime/Scripting/ScriptingManager.h"
#include "Runtime/Threads/Thread.h"
#include "Runtime/Scripting/Backend/IScriptingTypeProvider.h"

namespace Unity { class Component; class GameObject; }
extern const char* kUnityEngine;
extern const char* kMonoClasslibsProfile;
struct GUIState;
struct DomainReloadingData;

typedef dynamic_bitset AssemblyMask;

class MonoScript;
class MonoBehaviour;


/*
	The Mono Scripting runtime System consists of 3 classes.
	
	MonoManager
	MonoScript
	MonoBehaviour
	
	The MonoManager contains all information about the Assemblys it uses.
	(An assembly is an DLL or Exe containing the classes, metadata, and IL assembly code)
		
	When a MonoScript is loaded or rebuilt because the script has changed,
	the MonoManager is asked to lookup the MonoClass given by the script name.
	
	The MonoManager also keeps a lookup of ClassIDToMonoClass which is a precalculated list
	of classID's to their MonoClass* (The lookup respects inheritance so that when the C++ class is not availible as a MonoClass its parent Class is used instead)
		
	---------- continue.....
		
	MonoExport.cpp is used to wrap all the C++ objects eg. Transform
*/


typedef void ScriptsDidChangeCallback ();

// TODO: remove
MonoObject* MonoInstantiateScriptingWrapperForClassID(int classID);

class EXPORT_COREMODULE MonoManager : public ScriptingManager, public IScriptingTypeProvider
{
	public:
	REGISTER_DERIVED_CLASS (MonoManager, GlobalGameManager)
	DECLARE_OBJECT_SERIALIZE (MonoManager)

	MonoManager (MemLabelId label, ObjectCreationMode mode);
	// virtual ~MonoManager (); declared-by-macro
	
	virtual void AwakeFromLoad (AwakeFromLoadMode awakeMode);

	// If 'theNameSpace' is NULL then search is in any namespace
	MonoClass* GetMonoClassCaseInsensitive (const char* className, const char* theNameSpace = NULL);
	// If 'theNameSpace' is NULL then search is in any namespace
	MonoClass* GetMonoClass (const char* className, const char* theNameSpace = NULL);
	
	// Returns the class with className in the assembly defined by identifier (normally the pathname extension of the script)
	MonoClass* GetMonoClassWithAssemblyName (const std::string& className, const string& nameSpace, const string& identifier);

	/// Reloads all assemblies with assemblymask. If the assembly can be loaded, the bit for that assembly is cleared.
	/// Returns which assemblies could be loaded

#if UNITY_EDITOR
	enum { kEngineAssembly = 0, kEditorAssembly = 1, kLocatorAssembly = 2, kScriptAssemblies = 3 };
#else
	enum { kEngineAssembly = 0, kEditorAssembly = 1, kScriptAssemblies = 2 };
#endif
	enum AssemblyLoadFailure { kEverythingLoaded = 0, kFailedLoadingScriptAssemblies = 1, kFailedLoadingEngineOrEditorAssemblies = 2 };
	AssemblyLoadFailure ReloadAssembly (AssemblyMask allAssembliesMask);

	AssemblyMask GetSystemAssemblyMask (bool load);
	AssemblyMask GetAvailableDllAssemblyMask ();

	MonoImage* GetEngineImage () { return m_ScriptImages[kEngineAssembly]; }
	
	std::string GetAssemblyPath (int index);
	MonoAssembly* GetAssembly (int index);
	
	std::string GetAssemblyIdentifierFromImage(MonoImage* image);
	int GetAssemblyIndexFromImage(MonoImage* image);

	void AssertInvalidAssembly (MonoClass* klass);
	
	MonoClass* GetBuiltinMonoClass (const char* name, bool optional = false);
	
	int GetAssemblyCount() const {return m_AssemblyNames.size(); }
	int GetAssemblyIndexFromAssemblyName (const string& identifier);

	void UnloadAllAssembliesOnNextDomainReload();

	#if UNITY_EDITOR

	void ResizeAssemblyNames(int max);

	// The assembly name should never be changed when mono dll's have already been loaded.	
	void SetAssemblyName (unsigned index, const string& name);

	void RegisterScriptsChanged (ScriptsDidChangeCallback* func);

	// Called when the domain and UnityEngine/UnityEditor have been reloaded but before anything else is,
	// to give a chance for other dlls to be loaded before anything else (i.e., package manager)
	void SetLogAssemblyReload (bool reload) { m_LogAssemblyReload = reload; }

	MonoClass* GetBuiltinEditorMonoClass (const char* name);

	int InsertAssemblyName(const std::string& assemblyName);
	void SetCustomDllPathLocation (const std::string& name, const std::string& path);
	
	bool HasCompileErrors () { return m_HasCompileErrors; }
	void SetHasCompileErrors (bool compileErrors);
	
	std::vector<UnityStr>& GetRawAssemblyNames () { return m_AssemblyNames; }
	
	#else
	bool HasCompileErrors () { return false; }
	#endif
	
	
	//implementation of IScriptingTypeProvider
	BackendNativeType NativeTypeFor(const char* namespaze, const char* className);
	ScriptingTypePtr Provide(BackendNativeType nativeType);
	void Release(ScriptingTypePtr klass);

	private:

	void SetupLoadedEditorAssemblies ();
	AssemblyLoadFailure BeginReloadAssembly (DomainReloadingData& savedData);
	AssemblyLoadFailure EndReloadAssembly (const DomainReloadingData& savedData, AssemblyMask allAssembliesMask);

	// Rebuilds the m_ClassIDToMonoClass lookup table.
	// m_ClassIDToMonoClass maps from the classID to the MonoClass it is best represented by.
	// If a MonoClass can't be found for the exact type the next parent class is used instead
	void RebuildClassIDToScriptingClass ();
	void CleanupClassIDMaps();
	// Initializes in the CommonMonoTypes struct
	virtual void RebuildCommonMonoClasses ();
	
	bool LoadAssemblies (AssemblyMask allAssembliesMask);
	void PopulateAssemblyReferencingDomain();
	
	
	typedef std::vector<MonoImage*> ScriptImages;

	ScriptImages                 m_ScriptImages;

	std::vector<UnityStr>        m_AssemblyNames;
		
	std::vector<MonoVTable*>     m_ClassIDToVTable;
	
	bool                         m_HasCompileErrors;
	static UNITY_TLS_VALUE(bool) m_IsMonoBehaviourInConstructor;

	MonoDomain*                  m_AssemblyReferencingDomain;
	bool IsThisFileAnAssemblyThatCouldChange(std::string& path);

	#if UNITY_EDITOR
	DateTime                     m_EngineDllModDate;

	typedef std::map<std::string, std::string> CustomDllLocation;
	CustomDllLocation            m_CustomDllLocation;
	bool                         m_LogAssemblyReload;
	string                       m_ManagedEditorAssembliesBasePath;
	#endif
};

EXPORT_COREMODULE MonoManager& GetMonoManager ();
MonoManager* GetMonoManagerPtr ();


namespace MonoPathContainer
{
	std::vector<std::string>& GetMonoPaths();
	void AppendMonoPath (const string& path);
};

MonoMethod* FindStaticMonoMethod (MonoImage* image, const char* className, const char* nameSpace, const char* methodName);
MonoMethod* FindStaticMonoMethod (const char* className, const char* methodName);
MonoMethod* FindStaticMonoMethod (const char* nameSpace, const char* className, const char* methodName);

/// This has to be called from main to initialize mono
bool InitializeMonoFromMain (const std::vector<string>& monoPaths, string monoConfigPath, int argc, const char** argv, bool enableDebugger=false);
void CleanupMono ();
bool CleanupMonoReloadable ();

#if UNITY_RELEASE
#define AssertInvalidClass(x)
#else
#define AssertInvalidClass(x) GetMonoManager().AssertInvalidAssembly(x);
#endif

std::string MdbFile (const string& path);
std::string PdbFile (const string& path);

void DisableLoadSeperateDomain ();

MonoDomain* CreateDomain ();

void RegisterUnloadDomainCallback (ScriptsDidChangeCallback* call);

void PostprocessStacktrace(const char* stackTrace, std::string& processedStackTrace);

void ClearLogCallback ();

#endif //ENABLE_SCRIPTING
#endif