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