Welcome to mirror list, hosted at ThFree Co, Russian Federation.

embedded-api « docs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: f44f4ed15cad9abbf2274dc5d336b5e1e7f51e5d (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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
	
	   Embedding the Mono runtime, preliminary version
		 Miguel de Icaza (miguel@ximian.com),
		   Paolo Molaro (lupus@ximian.com)


	This document describes how to embed the Mono runtime in your
	application, and how to invoke CIL methods from C, and how to
	invoke C code from CIL. Both the JIT and interpreter can be
	embedded in very similar ways so most of what is described
	here can be used in either case.

* IMPORTANT

	This document is now outdated, see:

		http://www.mono-project.com/Embedding_Mono

        For an up-to-date version of this document

* Embedding the runtime.

	Embedding the runtime consists of various steps: 

		* Compiling and linking the Mono runtime

		* Initializing the Mono runtime

		* Optionally expose C code to the C#/CIL universe.

	These are discussed in detail next.

** Compiling and Linking

	To embed the runtime, you have to link your code against the
	Mono runtime libraries.  To do this, you want to pass the
	flags returned by pkg-config to your compiler:

		pkg-config --cflags --libs mono

	is used to get the flags for the JIT runtime and

		pkg-config --cflags --libs mint

	for the interpreted runtime.

	Like this:

		gcc sample.c `pkg-config --cflags --libs mono`

	You can separate the compilation flags from the linking flags, for 
	instance, you can use the following macros in your makefile:

		CFLAGS=`pkg-config --cflags mono`
		LDFLAGS=`pkg-config --libs mono`

** Initializing the Mono runtime

	To initialize the JIT runtime, call mono_jit_init, like this:

		#include <mono/mini/jit.h>

		MonoDomain *domain;

		domain = mono_jit_init ("domain-name");

	For the interpreted runtime use mono_interp_init instead:

		#include <mono/interpreter/embed.h>

		MonoDomain *domain;

		domain = mono_interp_init ("domain-name");

	That will return a MonoDomain where your code will be
	executed.  You can create multiple domains.  Each domain is
	isolated from the other domains and code in one domain will
	not interfere with code in other domains.  This is useful if
	you want to host different applications in your program.  

	Now, it is necessary to transfer control to Mono, and setup
	the threading infrastructure, you do this like this:

		void *user_data = NULL;

		mono_runtime_exec_managed_code (domain, main_thread_handler, user_data);

	Where your main_thread_handler can load your assembly and execute it:

	static void main_thread_handler (gpointer user_data)

		MonoAssembly *assembly;

		assembly = mono_domain_assembly_open (domain, "file.dll");
		if (!assembly)
			error ();

	In the above example, the contents of `file.dll' will be
	loaded into the domain.  This only loads the code, but it will
	not execute anything yet.  You can replace `file.dll' with
	another transport file, like `file.exe'

	To start executing code, you must invoke a method in the
	assembly, or if you have provided a static Main method (an
	entry point), you can use the convenience function:

		retval = mono_jit_exec (domain, assembly, argc - 1, argv + 1);

	or when using the interpreter use:

		retval = mono_interp_exec (domain, assembly, argc - 1, argv + 1);

	If you want to invoke a different method, look at the
	`Invoking Methods in the CIL universe' section later on.

** Shutting down the runtime

	To shutdown the Mono runtime, you have to clean up all the
	domains that were created, use this function:

		mono_jit_cleanup (domain);

	Or in the case of the interpreted runtime use:

		mono_interp_cleanup (domain);

** Applications that use threads.

	The Boehm GC system needs to catch your calls to the pthreads
	layer, so in each file where you use pthread.h you should
	include the <gc/gc.h> file.  

	If you can not do this for any reasons, just remember that you
	can not store pointers to Mono Objects on the stack, you can
	store them safely in the heap, or in global variables though

* Exposing C code to the CIL universe

	The Mono runtime provides two mechanisms to expose C code to
	the CIL universe: internal calls and native C code.   Internal
	calls are tightly integrated with the runtime, and have the
	least overhead, as they use the same data types that the
	runtime uses.

	The other option is to use the Platform Invoke (P/Invoke) to
	call C code from the CIL universe, using the standard P/Invoke
	mechanisms.

	To register an internal call, use this call in the C code:

	mono_add_internal_call ("Hello::Sample", sample);

	Now, you need to declare this on the C# side:

		using System;
		using System.Runtime.CompilerServices;

	class Hello {
		[MethodImplAttribute(MethodImplOptions.InternalCall)]
		extern static string Sample ();
	}

	Since this routine returns a string, here is the C definition:

		static MonoString*
		Sample () 
		{
			return mono_string_new (mono_domain_get (), "Hello!");
		}

	Notice that we have to return a `MonoString', and we use the
	`mono_string_new' API call to obtain this from a string.

* Invoking Methods in the CIL universe

	Calling a method in the CIL universe from C requires a number of steps:

		* Obtaining the MonoMethod handle to the method.

		* The method invocation.

** Obtaining a MonoMethod

	To get a MonoMethod there are several ways.

	You can get a MonoClass (the structure representing a type)
	using:

	MonoClass *
	mono_class_from_name (MonoImage *image, const char* name_space, const char *name);

	and then loop in the returned class method array until you get
	the one you're looking for. There are examples of such
	searches as static functions in several C files in
	metadata/*.c: we need to expose one through the API and remove
	the duplicates.

	The other, simpler, way is to use the functions in
	debug-helpers.h: there are examples of their use in monograph,
	mint and the jit as well.  You basically use a string
	description of the method, like:
	
	        "System.Object:GetHashCode()"
	
	and create a MonoMethodDesc out of it with:
	
	MonoMethodDesc* mono_method_desc_new (const char *name, gboolean include_namespace);
	
	You can then use:
	
	MonoMethod*     mono_method_desc_search_in_class (MonoMethodDesc *desc, MonoClass *klass);
	MonoMethod*     mono_method_desc_search_in_image (MonoMethodDesc *desc, MonoImage *image);
	
	to search for the method in a class or in an image.  You would
	tipically do this just once at the start of the program and
	store the result for reuse somewhere.
			
** Invoking a Method

	There are two functions to call a managed method:
	
	MonoObject*
	mono_runtime_invoke         (MonoMethod *method, void *obj, void **params,
	                             MonoObject **exc);
	and
	MonoObject*
	mono_runtime_invoke_array   (MonoMethod *method, void *obj, MonoArray *params,
	                             MonoObject **exc);
	
	obj is the 'this' pointer, it should be NULL for static
	methods, a MonoObject* for object instances and a pointer to
	the value type for value types.

	These functions can be used in both the JIT and the interpreted
	environments.

	The params array contains the arguments to the method with the
	same convention: MonoObject* pointers for object instances and
	pointers to the value type otherwise. The _invoke_array
	variant takes a C# object[] as the params argument (MonoArray
	*params): in this case the value types are boxed inside the
	respective reference representation.
	
	From unmanaged code you'll usually use the
	mono_runtime_invoke() variant.

	Note that this function doesn't handle virtual methods for
	you, it will exec the exact method you pass: we still need to
	expose a function to lookup the derived class implementation
	of a virtual method (there are examples of this in the code,
	though).

	You can pass NULL as the exc argument if you don't want to
	catch exceptions, otherwise, *exc will be set to the exception
	thrown, if any.  if an exception is thrown, you can't use the
	MonoObject* result from the function.

	If the method returns a value type, it is boxed in an object
	reference.
	
	We have plans for providing an additional method that returns
	an unmanaged->managed thunk like this:
	
	void* mono_method_get_unmanaged_thunk (MonoMethod *method);
	
	You'll be able to store the returned pointer in a function
	pointer with the proper signature and call that directly from
	C:
	
	typedef gint32 (*GetHashCode) (MonoObject *obj);
	
	GetHashCode func = mono_method_get_unmanaged_thunk (System_Object_GetHashCode_method);
	
	gint32 hashvalue = func (myobject);
	
	It may not be possible to manage exceptions in that case,
	though. I need to think more about it.

** Threading issues

	If your application creates threads on its own, and you want them to 
	be able to call code into the CIL universe with Mono, you have to
	register the thread with Mono before issuing the call.

	To do so, call the mono_thread_attach() function before you execute
	any managed code from the thread

* Samples

	See the sample programs in mono/sample/embed for examples of
	embedding the Mono runtime in your application.