Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'web/embedded-api')
-rwxr-xr-xweb/embedded-api305
1 files changed, 305 insertions, 0 deletions
diff --git a/web/embedded-api b/web/embedded-api
new file mode 100755
index 00000000000..3b405c98ddd
--- /dev/null
+++ b/web/embedded-api
@@ -0,0 +1,305 @@
+* Embedding the Mono runtime, preliminary version
+
+ This document describes how to embed the Mono runtime in your
+ application, and how to invoke CIL methods from C, and how to
+ invoke C code from CIL
+
+ Slides for Paolo's presentation at .NET ONE on the embedding
+ API are available here: <a
+ href="http://primates.ximian.com/~lupus/slides/embed">Hosting the Mono
+ Runtime</a>. You can also get his <a
+ href="http://primates.ximian.com/~lupus/slides/embed/Mono-0.01.tar.gz">sample
+ Mono module for Perl</a>
+
+ Authors: Paolo Molaro, Miguel de Icaza.
+
+* Embedding the runtime.
+
+ Embedding the runtime consists of various steps:
+
+ <ul>
+ * Compiling and linking the Mono runtime
+
+ * Initializing the Mono runtime
+
+ * Optionally expose C code to the C#/CIL universe.
+
+ </ul>
+
+ These are discussed in detail next.
+
+** Compiling and Linking
+
+ To embed the runtime, you have to link your code against the
+ Mono runtime libraries. To do this, you want to pass the
+ flags returned by pkg-config to your compiler:
+
+ <pre>
+ pkg-config --cflags --libs mono
+ </pre>
+
+ Like this:
+
+ <pre>
+ gcc sample.c `pkg-config --cflags --libs mono`
+ </pre>
+
+ You can separate the compilation flags from the linking flags, for
+ instance, you can use the following macros in your makefile:
+
+ <pre>
+ CFLAGS=`pkg-config --cflags mono`
+ LDFLAGS=`pkg-config --libs mono`
+ </pre>
+
+** Initializing the Mono runtime
+
+ To initialize the runtime, call mono_jit_init, like this:
+
+ <pre>
+ MonoDomain *domain;
+
+ domain = mono_jit_init ("domain-name");
+ </pre>
+
+ That will return a MonoDomain where your code will be
+ executed. You can create multiple domains. Each domain is
+ isolated from the other domains and code in one domain will
+ not interfere with code in other domains. This is useful if
+ you want to host different applications in your program.
+
+ Now, it is necessary to transfer control to Mono, and setup
+ the threading infrastructure, you do this like this:
+
+ <pre>
+ void *user_data = NULL;
+
+ mono_runtime_exec_managed_code (domain, main_thread_handler, user_data);
+ </pre>
+
+ Where your main_thread_handler can load your assembly and execute it:
+
+ <pre>
+ static void main_thread_handler (gpointer user_data)
+ {
+ MonoAssembly *assembly;
+
+ assembly = mono_domain_assembly_open (domain, "file.dll");
+ if (!assembly)
+ error ();
+ </pre>
+
+ In the above example, the contents of `file.dll' will be
+ loaded into the domain. This only loads the code, but it will
+ not execute anything yet. You can replace `file.dll' with
+ another transport file, like `file.exe'
+
+ To start executing code, you must invoke a method in the
+ assembly, or if you have provided a static Main method (an
+ entry point), you can use the convenience function:
+
+ <pre>
+ retval = mono_jit_exec (domain, assembly, argc - 1, argv + 1);
+ </pre>
+
+ If you want to invoke a different method, look at the
+ `Invoking Methods in the CIL universe' section later on.
+
+** Shutting down the runtime
+
+ To shutdown the Mono runtime, you have to clean up all the
+ domains that were created, use this function:
+
+ <pre>
+ mono_jit_cleanup (domain);
+ </pre>
+
+** Applications that use threads.
+
+ The Boehm GC system needs to catch your calls to the pthreads
+ layer, so in each file where you use pthread.h you should
+ include the &lt;gc/gc.h&gt; file.
+
+ If you can not do this for any reasons, just remember that you
+ can not store pointers to Mono Objects on the stack, you can
+ store them safely in the heap, or in global variables though
+
+* Exposing C code to the CIL universe
+
+ The Mono runtime provides two mechanisms to expose C code to
+ the CIL universe: internal calls and native C code. Internal
+ calls are tightly integrated with the runtime, and have the
+ least overhead, as they use the same data types that the
+ runtime uses.
+
+ The other option is to use the Platform Invoke (P/Invoke) to
+ call C code from the CIL universe, using the standard P/Invoke
+ mechanisms.
+
+ To register an internal call, use this call in the C code:
+
+ <pre>
+ mono_add_internal_call ("Hello::Sample", sample);
+ </pre>
+
+ Now, you need to declare this on the C# side:
+
+ <pre>
+ using System;
+ using System.Runtime.CompilerServices;
+ </pre>
+
+
+ <pre>
+ class Hello {
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static string Sample ();
+ }
+ </pre>
+
+ Since this routine returns a string, here is the C definition:
+
+ <pre>
+ static MonoString*
+ Sample ()
+ {
+ return mono_string_new (mono_domain_get (), "Hello!");
+ }
+ </pre>
+
+ Notice that we have to return a `MonoString', and we use the
+ `mono_string_new' API call to obtain this from a string.
+
+* Invoking Methods in the CIL universe
+
+ Calling a method in the CIL universe from C requires a number of steps:
+
+ <ul>
+ * Obtaining the MonoMethod handle to the method.
+
+ * The method invocation.
+ </ul>
+
+** Obtaining a MonoMethod
+
+ To get a MonoMethod there are several ways.
+
+ You can get a MonoClass (the structure representing a type)
+ using:
+
+ <pre>
+ MonoClass *
+ mono_class_from_name (MonoImage *image, const char* name_space, const char *name);
+ </pre>
+
+ and then loop in the returned class method array until you get
+ the one you're looking for. There are examples of such
+ searches as static functions in several C files in
+ metadata/*.c: we need to expose one through the API and remove
+ the duplicates.
+
+ The other, simpler, way is to use the functions in
+ debug-helpers.h: there are examples of their use in monograph,
+ mint and the jit as well. You basically use a string
+ description of the method, like:
+
+ <pre>
+ "System.Object:GetHashCode()"
+ </pre>
+
+ and create a MonoMethodDesc out of it with:
+
+ <pre>
+ MonoMethodDesc* mono_method_desc_new (const char *name, gboolean include_namespace);
+ </pre>
+
+ You can then use:
+
+ <pre>
+ MonoMethod* mono_method_desc_search_in_class (MonoMethodDesc *desc, MonoClass *klass);
+ MonoMethod* mono_method_desc_search_in_image (MonoMethodDesc *desc, MonoImage *image);
+ </pre>
+
+ to search for the method in a class or in an image. You would
+ tipically do this just once at the start of the program and
+ store the result for reuse somewhere.
+
+** Invoking a Method
+
+ There are two functions to call a managed method:
+
+ <pre>
+ MonoObject*
+ mono_runtime_invoke (MonoMethod *method, void *obj, void **params,
+ MonoObject **exc);
+ and
+ MonoObject*
+ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
+ MonoObject **exc);
+ </pre>
+
+ obj is the 'this' pointer, it should be NULL for static
+ methods, a MonoObject* for object instances and a pointer to
+ the value type for value types.
+
+ The params array contains the arguments to the method with the
+ same convention: MonoObject* pointers for object instances and
+ pointers to the value type otherwise. The _invoke_array
+ variant takes a C# object[] as the params argument (MonoArray
+ *params): in this case the value types are boxed inside the
+ respective reference representation.
+
+ From unmanaged code you'll usually use the
+ mono_runtime_invoke() variant.
+
+ Note that this function doesn't handle virtual methods for
+ you, it will exec the exact method you pass: we still need to
+ expose a function to lookup the derived class implementation
+ of a virtual method (there are examples of this in the code,
+ though).
+
+ You can pass NULL as the exc argument if you don't want to
+ catch exceptions, otherwise, *exc will be set to the exception
+ thrown, if any. if an exception is thrown, you can't use the
+ MonoObject* result from the function.
+
+ If the method returns a value type, it is boxed in an object
+ reference.
+
+ We have plans for providing an additional method that returns
+ an unmanaged->managed thunk like this:
+
+ <pre>
+ void* mono_method_get_unmanaged_thunk (MonoMethod *method);
+ </pre>
+
+ You'll be able to store the returned pointer in a function
+ pointer with the proper signature and call that directly from
+ C:
+
+ <pre>
+ typedef gint32 (*GetHashCode) (MonoObject *obj);
+
+ GetHashCode func = mono_method_get_unmanaged_thunk (System_Object_GetHashCode_method);
+
+ gint32 hashvalue = func (myobject);
+ </pre>
+
+ It may not be possible to manage exceptions in that case,
+ though. I need to think more about it.
+
+** Threading issues
+
+ If your application creates threads on its own, and you want them to
+ be able to call code into the CIL universe with Mono, you have to
+ register the thread with Mono before issuing the call.
+
+ To do so, call the mono_thread_attach() function before you execute
+ any managed code from the thread
+
+* Samples
+
+ See the sample programs in mono/sample/embed for examples of
+ embedding the Mono runtime in your application.
+
+