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