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