*** empty log message ***
[mono.git] / doc / 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         Then you can load an assembly containing code into the domain:
72
73         <pre>
74                 MonoAssembly *assembly;
75
76                 assembly = mono_domain_assembly_open (domain, "file.dll");
77                 if (!assembly)
78                         error ();
79         </pre>
80
81         In the above example, the contents of `file.dll' will be
82         loaded into the domain.  This only loads the code, but it will
83         not execute anything yet.  You can replace `file.dll' with
84         another transport file, like `file.exe'
85
86         To start executing code, you must invoke a method in the
87         assembly, or if you have provided a static Main method (an
88         entry point), you can use the convenience function:
89
90         <pre>
91                 retval = mono_jit_exec (domain, assembly, argc - 1, argv + 1);
92         </pre>
93
94         If you want to invoke a different method, look at the
95         `Invoking Methods in the CIL universe' section later on.
96
97 ** Shutting down the runtime
98
99         To shutdown the Mono runtime, you have to clean up all the
100         domains that were created, use this function:
101
102         <pre>
103                 mono_jit_cleanup (domain);
104         </pre>
105
106 ** Applications that use threads.
107
108         The Boehm GC system needs to catch your calls to the pthreads
109         layer, so in each file where you use pthread.h you should
110         include the <gc/gc.h> file.  
111
112 * Exposing C code to the CIL universe
113
114         The Mono runtime provides two mechanisms to expose C code to
115         the CIL universe: internal calls and native C code.   Internal
116         calls are tightly integrated with the runtime, and have the
117         least overhead, as they use the same data types that the
118         runtime uses.
119
120         The other option is to use the Platform Invoke (P/Invoke) to
121         call C code from the CIL universe, using the standard P/Invoke
122         mechanisms.
123
124         To register an internal call, use this call in the C code:
125
126         <pre>
127         mono_add_internal_call ("Hello::Sample", sample);
128         </pre>
129
130         Now, you need to declare this on the C# side:
131
132         <pre>
133                 using System;
134                 using System.Runtime.CompilerServices;
135         </pre>
136
137
138         <pre>
139         class Hello {
140                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
141                 extern static string Sample ();
142         }
143         </pre>
144
145         Since this routine returns a string, here is the C definition:
146
147         <pre>
148                 static MonoString*
149                 Sample () 
150                 {
151                         return mono_string_new (mono_domain_get (), "Hello!");
152                 }
153         </pre>
154
155         Notice that we have to return a `MonoString', and we use the
156         `mono_string_new' API call to obtain this from a string.
157
158 * Invoking Methods in the CIL universe
159
160         Calling a method in the CIL universe from C requires a number of steps:
161
162         <ul>
163                 * Obtaining the MonoMethod handle to the method.
164
165                 * The method invocation.
166         </ul>
167
168 ** Obtaining a MonoMethod
169
170         To get a MonoMethod there are several ways.
171
172         You can get a MonoClass (the structure representing a type)
173         using:
174
175         <pre>
176         MonoClass *
177         mono_class_from_name (MonoImage *image, const char* name_space, const char *name);
178         </pre>
179
180         and then loop in the returned class method array until you get
181         the one you're looking for. There are examples of such
182         searches as static functions in several C files in
183         metadata/*.c: we need to expose one through the API and remove
184         the duplicates.
185
186         The other, simpler, way is to use the functions in
187         debug-helpers.h: there are examples of their use in monograph,
188         mint and the jit as well.  You basically use a string
189         description of the method, like:
190         
191         <pre>
192                 "System.Object:GetHashCode()"
193         </pre>
194         
195         and create a MonoMethodDesc out of it with:
196         
197         <pre>
198         MonoMethodDesc* mono_method_desc_new (const char *name, gboolean include_namespace);
199         </pre>
200         
201         You can then use:
202         
203         <pre>
204         MonoMethod*     mono_method_desc_search_in_class (MonoMethodDesc *desc, MonoClass *klass);
205         MonoMethod*     mono_method_desc_search_in_image (MonoMethodDesc *desc, MonoImage *image);
206         </pre>
207         
208         to search for the method in a class or in an image.  You would
209         tipically do this just once at the start of the program and
210         store the result for reuse somewhere.
211                         
212 ** Invoking a Method
213
214         There are two functions to call a managed method:
215         
216         <pre>
217         MonoObject*
218         mono_runtime_invoke         (MonoMethod *method, void *obj, void **params,
219                                      MonoObject **exc);
220         and
221         MonoObject*
222         mono_runtime_invoke_array   (MonoMethod *method, void *obj, MonoArray *params,
223                                      MonoObject **exc);
224         </pre>
225         
226         obj is the 'this' pointer, it should be NULL for static
227         methods, a MonoObject* for object instances and a pointer to
228         the value type for value types.
229
230         The params array contains the arguments to the method with the
231         same convention: MonoObject* pointers for object instances and
232         pointers to the value type otherwise. The _invoke_array
233         variant takes a C# object[] as the params argument (MonoArray
234         *params): in this case the value types are boxed inside the
235         respective reference representation.
236         
237         From unmanaged code you'll usually use the
238         mono_runtime_invoke() variant.
239
240         Note that this function doesn't handle virtual methods for
241         you, it will exec the exact method you pass: we still need to
242         expose a function to lookup the derived class implementation
243         of a virtual method (there are examples of this in the code,
244         though).
245
246         You can pass NULL as the exc argument if you don't want to
247         catch exceptions, otherwise, *exc will be set to the exception
248         thrown, if any.  if an exception is thrown, you can't use the
249         MonoObject* result from the function.
250
251         If the method returns a value type, it is boxed in an object
252         reference.
253         
254         We have plans for providing an additional method that returns
255         an unmanaged->managed thunk like this:
256         
257         <pre>
258         void* mono_method_get_unmanaged_thunk (MonoMethod *method);
259         </pre>
260         
261         You'll be able to store the returned pointer in a function
262         pointer with the proper signature and call that directly from
263         C:
264         
265         <pre>
266         typedef gint32 (*GetHashCode) (MonoObject *obj);
267         
268         GetHashCode func = mono_method_get_unmanaged_thunk (System_Object_GetHashCode_method);
269         
270         gint32 hashvalue = func (myobject);
271         </pre>
272         
273         It may not be possible to manage exceptions in that case,
274         though. I need to think more about it.
275
276 ** Threading issues
277
278         If your application creates threads on its own, and you want them to 
279         be able to call code into the CIL universe with Mono, you have to
280         register the thread with Mono before issuing the call.
281
282         To do so, call the mono_thread_attach() function before you execute
283         any managed code from the thread
284
285 * Samples
286
287         See the sample programs in mono/sample/embed for examples of
288         embedding the Mono runtime in your application.
289
290