diff options
author | Miguel de Icaza <miguel@gnome.org> | 2002-08-01 20:07:04 +0400 |
---|---|---|
committer | Miguel de Icaza <miguel@gnome.org> | 2002-08-01 20:07:04 +0400 |
commit | d4230a9e74c0563aaf231cd3dbaf7437a60ce55e (patch) | |
tree | 1f73aea318b79793c5c12446a51b9447a1062029 /docs | |
parent | 8a345b11168d71e2c91497c402b83e2a57643076 (diff) |
Add embedded API document
svn path=/trunk/mono/; revision=6317
Diffstat (limited to 'docs')
-rw-r--r-- | docs/embedded-api | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/docs/embedded-api b/docs/embedded-api new file mode 100644 index 00000000000..b8fd31d47fc --- /dev/null +++ b/docs/embedded-api @@ -0,0 +1,227 @@ + + Embedding the Mono runtime, preliminary version + + Miguel de Icaza, Paolo Molaro. + + 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. + +* 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 + + 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 runtime, call mono_jit_init, like this: + + MonoDomain *domain; + + domain = mono_jit_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. + + Then you can load an assembly containing code into the domain: + + MonoAssembly *assembly; + + assembly = mono_domain_assembly_open ("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); + + 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); + +* 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. + + 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. + +* Samples + + See the sample programs inmono/sample/embed for examples of + embedding the Mono runtime in your application. + + |