Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / docs / embedded-api
1         
2            Embedding the Mono runtime, preliminary version
3                  Miguel de Icaza (miguel@ximian.com),
4                    Paolo Molaro (lupus@ximian.com)
5
6
7         This document describes how to embed the Mono runtime in your
8         application, and how to invoke CIL methods from C, and how to
9         invoke C code from CIL. Both the JIT and interpreter can be
10         embedded in very similar ways so most of what is described
11         here can be used in either case.
12
13 * IMPORTANT
14
15         This document is now outdated, see:
16
17                 http://www.mono-project.com/Embedding_Mono
18
19         For an up-to-date version of this document
20
21 * Embedding the runtime.
22
23         Embedding the runtime consists of various steps: 
24
25                 * Compiling and linking the Mono runtime
26
27                 * Initializing the Mono runtime
28
29                 * Optionally expose C code to the C#/CIL universe.
30
31         These are discussed in detail next.
32
33 ** Compiling and Linking
34
35         To embed the runtime, you have to link your code against the
36         Mono runtime libraries.  To do this, you want to pass the
37         flags returned by pkg-config to your compiler:
38
39                 pkg-config --cflags --libs mono
40
41         is used to get the flags for the JIT runtime and
42
43                 pkg-config --cflags --libs mint
44
45         for the interpreted runtime.
46
47         Like this:
48
49                 gcc sample.c `pkg-config --cflags --libs mono`
50
51         You can separate the compilation flags from the linking flags, for 
52         instance, you can use the following macros in your makefile:
53
54                 CFLAGS=`pkg-config --cflags mono`
55                 LDFLAGS=`pkg-config --libs mono`
56
57 ** Initializing the Mono runtime
58
59         To initialize the JIT runtime, call mono_jit_init, like this:
60
61                 #include <mono/mini/jit.h>
62
63                 MonoDomain *domain;
64
65                 domain = mono_jit_init ("domain-name");
66
67         For the interpreted runtime use mono_interp_init instead:
68
69                 #include <mono/interpreter/embed.h>
70
71                 MonoDomain *domain;
72
73                 domain = mono_interp_init ("domain-name");
74
75         That will return a MonoDomain where your code will be
76         executed.  You can create multiple domains.  Each domain is
77         isolated from the other domains and code in one domain will
78         not interfere with code in other domains.  This is useful if
79         you want to host different applications in your program.  
80
81         Now, it is necessary to transfer control to Mono, and setup
82         the threading infrastructure, you do this like this:
83
84                 void *user_data = NULL;
85
86                 mono_runtime_exec_managed_code (domain, main_thread_handler, user_data);
87
88         Where your main_thread_handler can load your assembly and execute it:
89
90         static void main_thread_handler (gpointer user_data)
91
92                 MonoAssembly *assembly;
93
94                 assembly = mono_domain_assembly_open (domain, "file.dll");
95                 if (!assembly)
96                         error ();
97
98         In the above example, the contents of `file.dll' will be
99         loaded into the domain.  This only loads the code, but it will
100         not execute anything yet.  You can replace `file.dll' with
101         another transport file, like `file.exe'
102
103         To start executing code, you must invoke a method in the
104         assembly, or if you have provided a static Main method (an
105         entry point), you can use the convenience function:
106
107                 retval = mono_jit_exec (domain, assembly, argc - 1, argv + 1);
108
109         or when using the interpreter use:
110
111                 retval = mono_interp_exec (domain, assembly, argc - 1, argv + 1);
112
113         If you want to invoke a different method, look at the
114         `Invoking Methods in the CIL universe' section later on.
115
116 ** Shutting down the runtime
117
118         To shutdown the Mono runtime, you have to clean up all the
119         domains that were created, use this function:
120
121                 mono_jit_cleanup (domain);
122
123         Or in the case of the interpreted runtime use:
124
125                 mono_interp_cleanup (domain);
126
127 ** Applications that use threads.
128
129         The Boehm GC system needs to catch your calls to the pthreads
130         layer, so in each file where you use pthread.h you should
131         include the <gc/gc.h> file.  
132
133         If you can not do this for any reasons, just remember that you
134         can not store pointers to Mono Objects on the stack, you can
135         store them safely in the heap, or in global variables though
136
137 * Exposing C code to the CIL universe
138
139         The Mono runtime provides two mechanisms to expose C code to
140         the CIL universe: internal calls and native C code.   Internal
141         calls are tightly integrated with the runtime, and have the
142         least overhead, as they use the same data types that the
143         runtime uses.
144
145         The other option is to use the Platform Invoke (P/Invoke) to
146         call C code from the CIL universe, using the standard P/Invoke
147         mechanisms.
148
149         To register an internal call, use this call in the C code:
150
151         mono_add_internal_call ("Hello::Sample", sample);
152
153         Now, you need to declare this on the C# side:
154
155                 using System;
156                 using System.Runtime.CompilerServices;
157
158         class Hello {
159                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
160                 extern static string Sample ();
161         }
162
163         Since this routine returns a string, here is the C definition:
164
165                 static MonoString*
166                 Sample () 
167                 {
168                         return mono_string_new (mono_domain_get (), "Hello!");
169                 }
170
171         Notice that we have to return a `MonoString', and we use the
172         `mono_string_new' API call to obtain this from a string.
173
174 * Invoking Methods in the CIL universe
175
176         Calling a method in the CIL universe from C requires a number of steps:
177
178                 * Obtaining the MonoMethod handle to the method.
179
180                 * The method invocation.
181
182 ** Obtaining a MonoMethod
183
184         To get a MonoMethod there are several ways.
185
186         You can get a MonoClass (the structure representing a type)
187         using:
188
189         MonoClass *
190         mono_class_from_name (MonoImage *image, const char* name_space, const char *name);
191
192         and then loop in the returned class method array until you get
193         the one you're looking for. There are examples of such
194         searches as static functions in several C files in
195         metadata/*.c: we need to expose one through the API and remove
196         the duplicates.
197
198         The other, simpler, way is to use the functions in
199         debug-helpers.h: there are examples of their use in monograph,
200         mint and the jit as well.  You basically use a string
201         description of the method, like:
202         
203                 "System.Object:GetHashCode()"
204         
205         and create a MonoMethodDesc out of it with:
206         
207         MonoMethodDesc* mono_method_desc_new (const char *name, gboolean include_namespace);
208         
209         You can then use:
210         
211         MonoMethod*     mono_method_desc_search_in_class (MonoMethodDesc *desc, MonoClass *klass);
212         MonoMethod*     mono_method_desc_search_in_image (MonoMethodDesc *desc, MonoImage *image);
213         
214         to search for the method in a class or in an image.  You would
215         tipically do this just once at the start of the program and
216         store the result for reuse somewhere.
217                         
218 ** Invoking a Method
219
220         There are two functions to call a managed method:
221         
222         MonoObject*
223         mono_runtime_invoke         (MonoMethod *method, void *obj, void **params,
224                                      MonoObject **exc);
225         and
226         MonoObject*
227         mono_runtime_invoke_array   (MonoMethod *method, void *obj, MonoArray *params,
228                                      MonoObject **exc);
229         
230         obj is the 'this' pointer, it should be NULL for static
231         methods, a MonoObject* for object instances and a pointer to
232         the value type for value types.
233
234         These functions can be used in both the JIT and the interpreted
235         environments.
236
237         The params array contains the arguments to the method with the
238         same convention: MonoObject* pointers for object instances and
239         pointers to the value type otherwise. The _invoke_array
240         variant takes a C# object[] as the params argument (MonoArray
241         *params): in this case the value types are boxed inside the
242         respective reference representation.
243         
244         From unmanaged code you'll usually use the
245         mono_runtime_invoke() variant.
246
247         Note that this function doesn't handle virtual methods for
248         you, it will exec the exact method you pass: we still need to
249         expose a function to lookup the derived class implementation
250         of a virtual method (there are examples of this in the code,
251         though).
252
253         You can pass NULL as the exc argument if you don't want to
254         catch exceptions, otherwise, *exc will be set to the exception
255         thrown, if any.  if an exception is thrown, you can't use the
256         MonoObject* result from the function.
257
258         If the method returns a value type, it is boxed in an object
259         reference.
260         
261         We have plans for providing an additional method that returns
262         an unmanaged->managed thunk like this:
263         
264         void* mono_method_get_unmanaged_thunk (MonoMethod *method);
265         
266         You'll be able to store the returned pointer in a function
267         pointer with the proper signature and call that directly from
268         C:
269         
270         typedef gint32 (*GetHashCode) (MonoObject *obj);
271         
272         GetHashCode func = mono_method_get_unmanaged_thunk (System_Object_GetHashCode_method);
273         
274         gint32 hashvalue = func (myobject);
275         
276         It may not be possible to manage exceptions in that case,
277         though. I need to think more about it.
278
279 ** Threading issues
280
281         If your application creates threads on its own, and you want them to 
282         be able to call code into the CIL universe with Mono, you have to
283         register the thread with Mono before issuing the call.
284
285         To do so, call the mono_thread_attach() function before you execute
286         any managed code from the thread
287
288 * Samples
289
290         See the sample programs in mono/sample/embed for examples of
291         embedding the Mono runtime in your application.
292
293