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 'docs/embedded-api')
-rw-r--r--docs/embedded-api284
1 files changed, 284 insertions, 0 deletions
diff --git a/docs/embedded-api b/docs/embedded-api
new file mode 100644
index 00000000000..76f45f8be73
--- /dev/null
+++ b/docs/embedded-api
@@ -0,0 +1,284 @@
+
+ Embedding the Mono runtime, preliminary version
+ Miguel de Icaza (miguel@ximian.com),
+ Paolo Molaro (lupus@ximian.com)
+
+ 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. Both the JIT and interpreter can be
+ embedded in very similar ways so most of what is described
+ here can be used in either case.
+
+* Embedding the runtime.
+
+ Embedding the runtime consists of various steps:
+
+ * Compiling and linking the Mono runtime
+
+ * Initializing the Mono runtime
+
+ * Optionally expose C code to the C#/CIL universe.
+
+ 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:
+
+ pkg-config --cflags --libs mono
+
+ is used to get the flags for the JIT runtime and
+
+ pkg-config --cflags --libs mint
+
+ for the interpreted runtime.
+
+ Like this:
+
+ gcc sample.c `pkg-config --cflags --libs mono`
+
+ You can separate the compilation flags from the linking flags, for
+ instance, you can use the following macros in your makefile:
+
+ CFLAGS=`pkg-config --cflags mono`
+ LDFLAGS=`pkg-config --libs mono`
+
+** Initializing the Mono runtime
+
+ To initialize the JIT runtime, call mono_jit_init, like this:
+
+ #include <mono/mini/jit.h>
+
+ MonoDomain *domain;
+
+ domain = mono_jit_init ("domain-name");
+
+ For the interpreted runtime use mono_interp_init instead:
+
+ #include <mono/interpreter/embed.h>
+
+ MonoDomain *domain;
+
+ domain = mono_interp_init ("domain-name");
+
+ 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:
+
+ void *user_data = NULL;
+
+ mono_runtime_exec_managed_code (domain, main_thread_handler, user_data);
+
+ Where your main_thread_handler can load your assembly and execute it:
+
+ static void main_thread_handler (gpointer user_data)
+
+ MonoAssembly *assembly;
+
+ assembly = mono_domain_assembly_open (domain, "file.dll");
+ if (!assembly)
+ error ();
+
+ 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:
+
+ retval = mono_jit_exec (domain, assembly, argc - 1, argv + 1);
+
+ or when using the interpreter use:
+
+ retval = mono_interp_exec (domain, assembly, argc - 1, argv + 1);
+
+ 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:
+
+ mono_jit_cleanup (domain);
+
+ Or in the case of the interpreted runtime use:
+
+ mono_interp_cleanup (domain);
+
+** 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 <gc/gc.h> 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:
+
+ mono_add_internal_call ("Hello::Sample", sample);
+
+ Now, you need to declare this on the C# side:
+
+ using System;
+ using System.Runtime.CompilerServices;
+
+ class Hello {
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static string Sample ();
+ }
+
+ Since this routine returns a string, here is the C definition:
+
+ static MonoString*
+ Sample ()
+ {
+ return mono_string_new (mono_domain_get (), "Hello!");
+ }
+
+ 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:
+
+ * Obtaining the MonoMethod handle to the method.
+
+ * The method invocation.
+
+** Obtaining a MonoMethod
+
+ To get a MonoMethod there are several ways.
+
+ You can get a MonoClass (the structure representing a type)
+ using:
+
+ MonoClass *
+ mono_class_from_name (MonoImage *image, const char* name_space, const char *name);
+
+ 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:
+
+ "System.Object:GetHashCode()"
+
+ and create a MonoMethodDesc out of it with:
+
+ MonoMethodDesc* mono_method_desc_new (const char *name, gboolean include_namespace);
+
+ You can then use:
+
+ MonoMethod* mono_method_desc_search_in_class (MonoMethodDesc *desc, MonoClass *klass);
+ MonoMethod* mono_method_desc_search_in_image (MonoMethodDesc *desc, MonoImage *image);
+
+ 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:
+
+ 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);
+
+ 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.
+
+ These functions can be used in both the JIT and the interpreted
+ environments.
+
+ 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:
+
+ void* mono_method_get_unmanaged_thunk (MonoMethod *method);
+
+ You'll be able to store the returned pointer in a function
+ pointer with the proper signature and call that directly from
+ C:
+
+ typedef gint32 (*GetHashCode) (MonoObject *obj);
+
+ GetHashCode func = mono_method_get_unmanaged_thunk (System_Object_GetHashCode_method);
+
+ gint32 hashvalue = func (myobject);
+
+ 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.
+
+