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