From 5cc5ea587dc98f1ddf3920462e3c48914e7d0a2a Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Fri, 31 Mar 2017 10:21:23 -0500 Subject: [PATCH] [objc] Simpler generator that, so far, only handle static properties (#29) The ObjC syntax for properties match the proposal from PR #25 [1]. Unit tests added for the matching features. [1] https://github.com/mono/Embeddinator-4000/pull/25 --- .gitignore | 1 + generator.sln | 35 ++ objcgen/driver.cs | 72 ++++ objcgen/generator.cs | 41 +++ objcgen/objcgen.csproj | 73 ++++ objcgen/objcgenerator.cs | 247 +++++++++++++ tests/managed/managed.csproj | 36 ++ tests/managed/properties.cs | 21 ++ tests/objc-cli/bindings.h | 22 ++ tests/objc-cli/bindings.m | 86 +++++ tests/objc-cli/glib.c | 464 +++++++++++++++++++++++++ tests/objc-cli/glib.h | 247 +++++++++++++ tests/objc-cli/libmanaged.dylib | Bin 0 -> 22284 bytes tests/objc-cli/mono_embeddinator.c | 279 +++++++++++++++ tests/objc-cli/mono_embeddinator.h | 222 ++++++++++++ tests/objc-cli/perf-cli | Bin 0 -> 8792 bytes tests/objc-cli/perf-test.m | 15 + tests/objc-cli/test-cli | Bin 0 -> 8824 bytes tests/objc-cli/test-managed.m | 15 + tests/objcgentest/ObjCGeneratorTest.cs | 27 ++ tests/objcgentest/objcgentest.csproj | 46 +++ 21 files changed, 1949 insertions(+) create mode 100644 generator.sln create mode 100644 objcgen/driver.cs create mode 100644 objcgen/generator.cs create mode 100644 objcgen/objcgen.csproj create mode 100644 objcgen/objcgenerator.cs create mode 100644 tests/managed/managed.csproj create mode 100644 tests/managed/properties.cs create mode 100644 tests/objc-cli/bindings.h create mode 100644 tests/objc-cli/bindings.m create mode 100644 tests/objc-cli/glib.c create mode 100644 tests/objc-cli/glib.h create mode 100755 tests/objc-cli/libmanaged.dylib create mode 100644 tests/objc-cli/mono_embeddinator.c create mode 100644 tests/objc-cli/mono_embeddinator.h create mode 100755 tests/objc-cli/perf-cli create mode 100644 tests/objc-cli/perf-test.m create mode 100755 tests/objc-cli/test-cli create mode 100644 tests/objc-cli/test-managed.m create mode 100644 tests/objcgentest/ObjCGeneratorTest.cs create mode 100644 tests/objcgentest/objcgentest.csproj diff --git a/.gitignore b/.gitignore index 2c6b46c..860f987 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ missing *.dll *.exe bin/ +obj/ *.userprefs *.pc .DS_Store diff --git a/generator.sln b/generator.sln new file mode 100644 index 0000000..98aabf5 --- /dev/null +++ b/generator.sln @@ -0,0 +1,35 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "objcgen", "objcgen\objcgen.csproj", "{C166803B-011F-4EAF-B8C2-D7DBBA3CF1EC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{21776062-DBDA-4408-BF22-9DCB2682DCBC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "objcgentest", "tests\objcgentest\objcgentest.csproj", "{076A871B-0C13-47D8-8923-B9242995BFF8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "managed", "tests\managed\managed.csproj", "{D56A7E3F-FF5C-4EC2-879F-1260ABBD1903}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C166803B-011F-4EAF-B8C2-D7DBBA3CF1EC}.Debug|x86.ActiveCfg = Debug|x86 + {C166803B-011F-4EAF-B8C2-D7DBBA3CF1EC}.Debug|x86.Build.0 = Debug|x86 + {C166803B-011F-4EAF-B8C2-D7DBBA3CF1EC}.Release|x86.ActiveCfg = Release|x86 + {C166803B-011F-4EAF-B8C2-D7DBBA3CF1EC}.Release|x86.Build.0 = Release|x86 + {076A871B-0C13-47D8-8923-B9242995BFF8}.Debug|x86.ActiveCfg = Debug|Any CPU + {076A871B-0C13-47D8-8923-B9242995BFF8}.Debug|x86.Build.0 = Debug|Any CPU + {076A871B-0C13-47D8-8923-B9242995BFF8}.Release|x86.ActiveCfg = Release|Any CPU + {076A871B-0C13-47D8-8923-B9242995BFF8}.Release|x86.Build.0 = Release|Any CPU + {D56A7E3F-FF5C-4EC2-879F-1260ABBD1903}.Debug|x86.ActiveCfg = Debug|Any CPU + {D56A7E3F-FF5C-4EC2-879F-1260ABBD1903}.Debug|x86.Build.0 = Debug|Any CPU + {D56A7E3F-FF5C-4EC2-879F-1260ABBD1903}.Release|x86.ActiveCfg = Release|Any CPU + {D56A7E3F-FF5C-4EC2-879F-1260ABBD1903}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {076A871B-0C13-47D8-8923-B9242995BFF8} = {21776062-DBDA-4408-BF22-9DCB2682DCBC} + {D56A7E3F-FF5C-4EC2-879F-1260ABBD1903} = {21776062-DBDA-4408-BF22-9DCB2682DCBC} + EndGlobalSection +EndGlobal diff --git a/objcgen/driver.cs b/objcgen/driver.cs new file mode 100644 index 0000000..3fe1243 --- /dev/null +++ b/objcgen/driver.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Text; + +using ObjC; + +namespace Embeddinator { + + static class Driver { + + // TODO: use Mono.Options + // TODO: add errors.cs + public static int Main (string [] args) + { + bool shared = true; // dylib + + Console.WriteLine ("Parsing assemblies..."); + + var assemblies = new List (); + foreach (var arg in args) { + assemblies.Add (Assembly.LoadFile (arg)); + Console.WriteLine ($"\tParsed '{arg}'"); + } + + // by default the first specified assembly + var name = Path.GetFileNameWithoutExtension (args [0]); + + Console.WriteLine ("Processing assemblies..."); + var g = new ObjCGenerator (); + g.Process (assemblies); + + Console.WriteLine ("Generating binding code..."); + g.Generate (assemblies); + g.Write (); + + var exe = typeof (Driver).Assembly; + foreach (var res in exe.GetManifestResourceNames ()) { + if (res == "main.c") { + // no main is needed for dylib and don't re-write an existing main.c file - it's a template + if (shared || File.Exists ("main.c")) + continue; + } + Console.WriteLine ($"\tGenerated: {res}"); + using (var sw = new StreamWriter (res)) + exe.GetManifestResourceStream (res).CopyTo (sw.BaseStream); + } + + Console.WriteLine ("Compiling binding code..."); + + StringBuilder options = new StringBuilder ("clang "); + options.Append ("-DMONO_EMBEDDINATOR_DLL_EXPORT "); + options.Append ("-framework CoreFoundation "); + options.Append ("-I\"/Library/Frameworks/Mono.framework/Versions/Current/include/mono-2.0\" -L\"/Library/Frameworks/Mono.framework/Versions/Current/lib/\" -lmonosgen-2.0 "); + options.Append ("glib.c mono_embeddinator.c bindings.m "); + if (shared) + options.Append ($"-dynamiclib -install_name lib{name}.dylib "); + else + options.Append ("main.c "); + options.Append ($"-o lib{name}.dylib -ObjC -lobjc"); + + Console.WriteLine ("Compiling binding code..."); + Console.WriteLine ($"\tInvoking: xcrun {options}"); + var p = Process.Start ("xcrun", options.ToString ()); + p.WaitForExit (); + Console.WriteLine ("Done"); + return 0; + } + } +} diff --git a/objcgen/generator.cs b/objcgen/generator.cs new file mode 100644 index 0000000..5f07bae --- /dev/null +++ b/objcgen/generator.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace Embeddinator { + + public class Generator { + + public virtual void Process (IEnumerable assemblies) + { + } + + public virtual void Generate (IEnumerable assemblies) + { + foreach (var a in assemblies) { + Generate (a); + } + } + + protected virtual void Generate (Assembly a) + { + foreach (var t in a.GetTypes ()) { + if (!t.IsPublic) + continue; + Generate (t); + } + } + + protected virtual void Generate (Type t) + { + } + + protected virtual void Generate (PropertyInfo pi) + { + } + + public virtual void Write () + { + } + } +} diff --git a/objcgen/objcgen.csproj b/objcgen/objcgen.csproj new file mode 100644 index 0000000..ab578f4 --- /dev/null +++ b/objcgen/objcgen.csproj @@ -0,0 +1,73 @@ + + + + Debug + x86 + {C166803B-011F-4EAF-B8C2-D7DBBA3CF1EC} + Exe + objcgen + objcgen + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + true + x86 + + + true + bin\Release + prompt + 4 + true + x86 + + + + + ..\packages\Mono.Options.4.4.0.0\lib\net4-client\Mono.Options.dll + + + + + + + main.c + + + + + + + + support\glib.c + glib.c + + + support\glib.h + glib.h + + + support\mono_embeddinator.c + mono_embeddinator.c + + + support\mono_embeddinator.h + mono_embeddinator.h + + + support\main.c + main.c + + + + + + + \ No newline at end of file diff --git a/objcgen/objcgenerator.cs b/objcgen/objcgenerator.cs new file mode 100644 index 0000000..6189086 --- /dev/null +++ b/objcgen/objcgenerator.cs @@ -0,0 +1,247 @@ +using System; +using System.Collections.Generic; +using System.IO; +// TODO: bad, need to choose either IKVM.Reflection or Cecil +using System.Reflection; + +using Embeddinator; + +namespace ObjC { + + public class ObjCGenerator : Generator { + + static TextWriter headers = new StringWriter (); + static TextWriter implementation = new StringWriter (); + + List types = new List (); + + public override void Process (IEnumerable assemblies) + { + foreach (var a in assemblies) { + foreach (var t in a.GetTypes ()) { + if (!t.IsPublic) + continue; + // gather types for forward declarations + types.Add (t); + } + } + Console.WriteLine ($"\t{types.Count} types found"); + } + + public override void Generate (IEnumerable assemblies) + { + headers.WriteLine ("#include \"mono_embeddinator.h\""); + headers.WriteLine ("#import "); + headers.WriteLine (); + headers.WriteLine ("MONO_EMBEDDINATOR_BEGIN_DECLS"); + headers.WriteLine (); + + headers.WriteLine ("// forward declarations"); + foreach (var t in types) + headers.WriteLine ($"@class {GetTypeName (t)};"); + headers.WriteLine (); + + implementation.WriteLine ("#include \"bindings.h\""); + implementation.WriteLine ("#include \"glib.h\""); + implementation.WriteLine ("#include "); + implementation.WriteLine ("#include "); + implementation.WriteLine ("#include "); + implementation.WriteLine ("#include "); + implementation.WriteLine ("#include "); + implementation.WriteLine (); + + implementation.WriteLine ("mono_embeddinator_context_t __mono_context;"); + implementation.WriteLine (); + + foreach (var a in assemblies) + implementation.WriteLine ($"MonoImage* __{a.GetName ().Name}_image;"); + implementation.WriteLine (); + + foreach (var t in types) + implementation.WriteLine ($"static MonoClass* {t.Name}_class = nil;"); + implementation.WriteLine (); + + implementation.WriteLine ("static void __initialize_mono ()"); + implementation.WriteLine ("{"); + implementation.WriteLine ("\tif (__mono_context.domain)"); + implementation.WriteLine ("\t\treturn;"); + implementation.WriteLine ("\tmono_embeddinator_init (&__mono_context, \"mono_embeddinator_binding\");"); + implementation.WriteLine ("}"); + implementation.WriteLine (); + + base.Generate (assemblies); + + headers.WriteLine (); + headers.WriteLine ("MONO_EMBEDDINATOR_END_DECLS"); + } + + protected override void Generate (Assembly a) + { + var name = a.GetName ().Name; + implementation.WriteLine ($"static void __lookup_assembly_{name} ()"); + implementation.WriteLine ("{"); + implementation.WriteLine ($"\tif (__{name}_image)"); + implementation.WriteLine ("\t\treturn;"); + implementation.WriteLine ($"\t__{name}_image = mono_embeddinator_load_assembly (&__mono_context, \"{name}.dll\");"); + implementation.WriteLine ("}"); + implementation.WriteLine (); + + foreach (var t in a.GetTypes ()) { + if (!t.IsPublic) + continue; + Generate (t); + } + } + + protected override void Generate (Type t) + { + var managed_name = t.Name; + implementation.WriteLine ($"static void __lookup_class_{managed_name} ()"); + implementation.WriteLine ("{"); + implementation.WriteLine ($"\tif (!{managed_name}_class) {{"); + implementation.WriteLine ("\t\t__initialize_mono ();"); + implementation.WriteLine ("\t\t__lookup_assembly_managed ();"); + implementation.WriteLine ($"\t\t{managed_name}_class = mono_class_from_name (__{t.Assembly.GetName ().Name}_image, \"\", \"{managed_name}\");"); + implementation.WriteLine ("\t}"); + implementation.WriteLine ("}"); + + var native_name = GetTypeName (t); + headers.WriteLine ($"// {t.AssemblyQualifiedName}"); + headers.WriteLine ($"@interface {native_name} : {GetTypeName (t.BaseType)} {{"); + headers.WriteLine ("\tMonoEmbedObject* _object;"); + headers.WriteLine ("}"); + + headers.WriteLine (); + if (t.IsSealed && t.IsAbstract) { + // don't allow instantiation of static types from ObjC code + headers.WriteLine ("// a .net static type cannot be initialized"); + headers.WriteLine ("- (instancetype)init NS_UNAVAILABLE;"); + headers.WriteLine (); + } + + implementation.WriteLine ($"// {t.AssemblyQualifiedName}"); + implementation.WriteLine ($"@implementation {managed_name}"); + implementation.WriteLine (); + + foreach (var pi in t.GetProperties ()) + Generate (pi); + + headers.WriteLine (); + headers.WriteLine ("@end"); + + implementation.WriteLine (); + implementation.WriteLine ("@end"); + } + + protected override void Generate (PropertyInfo pi) + { + var getter = pi.GetGetMethod (); + var setter = pi.GetSetMethod (); + // FIXME: setter only is valid, even if discouraged, in .NET - we should create a SetX method + if (getter == null && setter != null) + throw new NotSupportedException (); + + // TODO override with attribute ? e.g. [ObjC.Selector ("foo")] + var name = CamelCase (pi.Name); + + headers.Write ("@property (nonatomic"); + if (getter.IsStatic) + headers.Write (", class"); + if (setter == null) + headers.Write (", readonly"); + else + headers.Write (", readwrite"); + var property_type = GetTypeName (pi.PropertyType); + headers.WriteLine ($") {property_type} {name};"); + + var managed_type_name = pi.DeclaringType.Name; + implementation.Write (getter.IsStatic ? '+' : '-'); + implementation.WriteLine ($" ({property_type}) {name}"); + implementation.WriteLine ("{"); + implementation.WriteLine ($"\tconst char __method_name [] = \"{managed_type_name}:{getter.Name}()\";"); + implementation.WriteLine ("\tstatic MonoMethod* __method = nil;"); + implementation.WriteLine ("\tif (!__method) {"); + implementation.WriteLine ($"\t\t__lookup_class_{managed_type_name} ();"); + implementation.WriteLine ($"\t\t__method = mono_embeddinator_lookup_method (__method_name, {managed_type_name}_class);"); + implementation.WriteLine ("\t}"); + implementation.WriteLine ("\tMonoObject* __exception = nil;"); + implementation.WriteLine ("\tMonoObject* __result = mono_runtime_invoke (__method, nil, nil, &__exception);"); + implementation.WriteLine ("\tif (__exception)"); + implementation.WriteLine ("\t\tmono_embeddinator_throw_exception (__exception);"); + ReturnValue (pi.PropertyType); + implementation.WriteLine ("}"); + if (setter == null) + return; + + // TODO override with attribute ? e.g. [ObjC.Selector ("foo")] + implementation.Write (getter.IsStatic ? '+' : '-'); + implementation.WriteLine ($" (void) set{pi.Name}:({property_type})value"); + implementation.WriteLine ("{"); + implementation.WriteLine ($"\tconst char __method_name [] = \"{managed_type_name}:{setter.Name}({property_type})\";"); + implementation.WriteLine ("\tstatic MonoMethod* __method = nil;"); + implementation.WriteLine ("\tif (!__method) {"); + implementation.WriteLine ($"\t\t__lookup_class_{managed_type_name} ();"); + implementation.WriteLine ($"\t\t__method = mono_embeddinator_lookup_method (__method_name, {managed_type_name}_class);"); + implementation.WriteLine ("\t}"); + implementation.WriteLine ("\tvoid* __args [1];"); + implementation.WriteLine ("\t__args [0] = &value;"); + implementation.WriteLine ("\tMonoObject* __exception = nil;"); + implementation.WriteLine ("\tMonoObject* __result = mono_runtime_invoke (__method, nil, __args, &__exception);"); + implementation.WriteLine ("\tif (__exception)"); + implementation.WriteLine ("\t\tmono_embeddinator_throw_exception (__exception);"); + implementation.WriteLine ("}"); + } + + void ReturnValue (Type t) + { + switch (Type.GetTypeCode (t)) { + // unboxing + case TypeCode.Boolean: + case TypeCode.Int32: + var name = GetTypeName (t); + implementation.WriteLine ("\tvoid* __unbox = mono_object_unbox (__result);"); + implementation.WriteLine ($"\treturn *(({name}*)__unbox);"); + break; + default: + throw new NotSupportedException (); + } + } + + void WriteFile (string name, string content) + { + Console.WriteLine ($"\tGenerated: {name}"); + File.WriteAllText (name, content); + } + + public override void Write () + { + WriteFile ("bindings.h", headers.ToString ()); + WriteFile ("bindings.m", implementation.ToString ()); + } + + // TODO complete mapping (only with corresponding tests) + // TODO override with attribute ? e.g. [Obj.Name ("XAMType")] + public static string GetTypeName (Type t) + { + switch (Type.GetTypeCode (t)) { + case TypeCode.Object: + return t == typeof (object) ? "NSObject" : t.Name; + case TypeCode.Boolean: + return "bool"; + case TypeCode.Int32: + return "int"; + default: + throw new NotSupportedException (); + } + } + + public static string CamelCase (string s) + { + if (s == null) + return null; + if (s.Length == 0) + return String.Empty; + return Char.ToLowerInvariant (s [0]) + s.Substring (1, s.Length - 1); + } + } +} diff --git a/tests/managed/managed.csproj b/tests/managed/managed.csproj new file mode 100644 index 0000000..73bf101 --- /dev/null +++ b/tests/managed/managed.csproj @@ -0,0 +1,36 @@ + + + + Debug + AnyCPU + {D56A7E3F-FF5C-4EC2-879F-1260ABBD1903} + Library + managed + managed + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + true + bin\Release + prompt + 4 + false + + + + + + + + + \ No newline at end of file diff --git a/tests/managed/properties.cs b/tests/managed/properties.cs new file mode 100644 index 0000000..41a3c4c --- /dev/null +++ b/tests/managed/properties.cs @@ -0,0 +1,21 @@ +using System; + +// static type +public static class Platform { + + // static get-only property + public static bool IsWindows { + get { + switch (Environment.OSVersion.Platform) { + case PlatformID.Win32NT: + case PlatformID.Win32S: + case PlatformID.Win32Windows: + case PlatformID.WinCE: + return true; + } + return false; + } + } + + public static int ExitCode { get; set; } +} diff --git a/tests/objc-cli/bindings.h b/tests/objc-cli/bindings.h new file mode 100644 index 0000000..1ac59dd --- /dev/null +++ b/tests/objc-cli/bindings.h @@ -0,0 +1,22 @@ +#include "mono_embeddinator.h" +#import + +MONO_EMBEDDINATOR_BEGIN_DECLS + +// forward declarations +@class Platform; + +// Platform, managed, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null +@interface Platform : NSObject { + MonoEmbedObject* _object; +} + +// a .net static type cannot be initialized +- (instancetype)init NS_UNAVAILABLE; + +@property (nonatomic, class, readonly) bool isWindows; +@property (nonatomic, class, readwrite) int exitCode; + +@end + +MONO_EMBEDDINATOR_END_DECLS diff --git a/tests/objc-cli/bindings.m b/tests/objc-cli/bindings.m new file mode 100644 index 0000000..6817e57 --- /dev/null +++ b/tests/objc-cli/bindings.m @@ -0,0 +1,86 @@ +#include "bindings.h" +#include "glib.h" +#include +#include +#include +#include +#include + +mono_embeddinator_context_t __mono_context; + +MonoImage* __managed_image; + +static MonoClass* Platform_class = nil; + +static void __initialize_mono () +{ + if (__mono_context.domain) + return; + mono_embeddinator_init (&__mono_context, "mono_embeddinator_binding"); +} + +static void __lookup_assembly_managed () +{ + if (__managed_image) + return; + __managed_image = mono_embeddinator_load_assembly (&__mono_context, "managed.dll"); +} + +static void __lookup_class_Platform () +{ + if (!Platform_class) { + __initialize_mono (); + __lookup_assembly_managed (); + Platform_class = mono_class_from_name (__managed_image, "", "Platform"); + } +} +// Platform, managed, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null +@implementation Platform + ++ (bool) isWindows +{ + const char __method_name [] = "Platform:get_IsWindows()"; + static MonoMethod* __method = nil; + if (!__method) { + __lookup_class_Platform (); + __method = mono_embeddinator_lookup_method (__method_name, Platform_class); + } + MonoObject* __exception = nil; + MonoObject* __result = mono_runtime_invoke (__method, nil, nil, &__exception); + if (__exception) + mono_embeddinator_throw_exception (__exception); + void* __unbox = mono_object_unbox (__result); + return *((bool*)__unbox); +} ++ (int) exitCode +{ + const char __method_name [] = "Platform:get_ExitCode()"; + static MonoMethod* __method = nil; + if (!__method) { + __lookup_class_Platform (); + __method = mono_embeddinator_lookup_method (__method_name, Platform_class); + } + MonoObject* __exception = nil; + MonoObject* __result = mono_runtime_invoke (__method, nil, nil, &__exception); + if (__exception) + mono_embeddinator_throw_exception (__exception); + void* __unbox = mono_object_unbox (__result); + return *((int*)__unbox); +} ++ (void) setExitCode:(int)value +{ + const char __method_name [] = "Platform:set_ExitCode(int)"; + static MonoMethod* __method = nil; + if (!__method) { + __lookup_class_Platform (); + __method = mono_embeddinator_lookup_method (__method_name, Platform_class); + } + void* __args [1]; + __args [0] = &value; + MonoObject* __exception = nil; + MonoObject* __result = mono_runtime_invoke (__method, nil, __args, &__exception); + if (__exception) + mono_embeddinator_throw_exception (__exception); +} + +@end diff --git a/tests/objc-cli/glib.c b/tests/objc-cli/glib.c new file mode 100644 index 0000000..2c187a7 --- /dev/null +++ b/tests/objc-cli/glib.c @@ -0,0 +1,464 @@ +/* + * String functions + * + * Author: + * Miguel de Icaza (miguel@novell.com) + * Aaron Bockover (abockover@novell.com) + * + * (C) 2006 Novell, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include "glib.h" + +void g_free (void *ptr) +{ + free(ptr); +} + +gpointer g_realloc (gpointer obj, gsize size) +{ + return realloc(obj, size); +} + +gpointer g_malloc (gsize x) +{ + return malloc(x); +} + +gpointer g_malloc0 (gsize x) +{ + return calloc(1, x); +} + +gpointer +g_memdup (gconstpointer mem, guint byte_size) +{ + gpointer ptr; + + if (mem == NULL) + return NULL; + + ptr = g_malloc (byte_size); + if (ptr != NULL) + memcpy (ptr, mem, byte_size); + + return ptr; +} + +gchar * +g_strdup (const gchar *str) +{ + if (str) { return (gchar*) g_memdup (str, (guint)strlen (str) + 1); } + return NULL; +} + +#define INITIAL_CAPACITY 16 + +#define element_offset(p,i) ((p)->array.data + (i) * (p)->element_size) +#define element_length(p,i) ((i) * (p)->element_size) + +typedef struct { + GArray array; + gboolean clear_; + guint element_size; + gboolean zero_terminated; + guint capacity; +} GArrayPriv; + +static void +ensure_capacity (GArrayPriv *priv, guint capacity) +{ + guint new_capacity; + + if (capacity <= priv->capacity) + return; + + new_capacity = (capacity + 63) & ~63; + + priv->array.data = g_realloc (priv->array.data, element_length (priv, new_capacity)); + + if (priv->clear_) { + memset (element_offset (priv, priv->capacity), + 0, + element_length (priv, new_capacity - priv->capacity)); + } + + priv->capacity = new_capacity; +} + +GArray * +g_array_new (gboolean zero_terminated, + gboolean clear_, + guint element_size) +{ + GArrayPriv *rv = g_new0 (GArrayPriv, 1); + rv->zero_terminated = zero_terminated; + rv->clear_ = clear_; + rv->element_size = element_size; + + ensure_capacity (rv, INITIAL_CAPACITY); + + return (GArray*)rv; +} + +GArray * +g_array_sized_new (gboolean zero_terminated, + gboolean clear_, + guint element_size, + guint reserved_size) +{ + GArrayPriv *rv = g_new0 (GArrayPriv, 1); + rv->zero_terminated = zero_terminated; + rv->clear_ = clear_; + rv->element_size = element_size; + + ensure_capacity (rv, reserved_size); + + return (GArray*)rv; +} + +gchar* +g_array_free (GArray *array, + gboolean free_segment) +{ + gchar* rv = NULL; + + g_return_val_if_fail (array != NULL, NULL); + + if (free_segment) + g_free (array->data); + else + rv = array->data; + + g_free (array); + + return rv; +} + +GArray * +g_array_append_vals (GArray *array, + gconstpointer data, + guint len) +{ + GArrayPriv *priv = (GArrayPriv*)array; + + g_return_val_if_fail (array != NULL, NULL); + + ensure_capacity (priv, priv->array.len + len + (priv->zero_terminated ? 1 : 0)); + + memmove (element_offset (priv, priv->array.len), + data, + element_length (priv, len)); + + priv->array.len += len; + + if (priv->zero_terminated) { + memset (element_offset (priv, priv->array.len), + 0, + priv->element_size); + } + + return array; +} + +GArray* +g_array_insert_vals (GArray *array, + guint index_, + gconstpointer data, + guint len) +{ + GArrayPriv *priv = (GArrayPriv*)array; + guint extra = (priv->zero_terminated ? 1 : 0); + + g_return_val_if_fail (array != NULL, NULL); + + ensure_capacity (priv, array->len + len + extra); + + /* first move the existing elements out of the way */ + memmove (element_offset (priv, index_ + len), + element_offset (priv, index_), + element_length (priv, array->len - index_)); + + /* then copy the new elements into the array */ + memmove (element_offset (priv, index_), + data, + element_length (priv, len)); + + array->len += len; + + if (priv->zero_terminated) { + memset (element_offset (priv, priv->array.len), + 0, + priv->element_size); + } + + return array; +} + +GArray* +g_array_remove_index (GArray *array, + guint index_) +{ + GArrayPriv *priv = (GArrayPriv*)array; + + g_return_val_if_fail (array != NULL, NULL); + + memmove (element_offset (priv, index_), + element_offset (priv, index_ + 1), + element_length (priv, array->len - index_)); + + array->len --; + + if (priv->zero_terminated) { + memset (element_offset (priv, priv->array.len), + 0, + priv->element_size); + } + + return array; +} + +GArray* +g_array_remove_index_fast (GArray *array, + guint index_) +{ + GArrayPriv *priv = (GArrayPriv*)array; + + g_return_val_if_fail (array != NULL, NULL); + + memmove (element_offset (priv, index_), + element_offset (priv, array->len - 1), + element_length (priv, 1)); + + array->len --; + + if (priv->zero_terminated) { + memset (element_offset (priv, priv->array.len), + 0, + priv->element_size); + } + + return array; +} + +void +g_array_set_size (GArray *array, gint length) +{ + GArrayPriv *priv = (GArrayPriv*)array; + + g_return_if_fail (array != NULL); + g_return_if_fail (length >= 0); + + if (length == priv->capacity) + return; // nothing to be done + + if (length > priv->capacity) { + // grow the array + ensure_capacity (priv, length); + } + + array->len = length; +} + +#define GROW_IF_NECESSARY(s,l) { \ + if(s->len + l >= s->allocated_len) { \ + s->allocated_len = (s->allocated_len + l + 16) * 2; \ + s->str = g_realloc(s->str, s->allocated_len); \ + } \ +} + +GString * +g_string_new_len (const gchar *init, gssize len) +{ + GString *ret = g_new (GString, 1); + + if (init == NULL) + ret->len = 0; + else + ret->len = len < 0 ? strlen(init) : len; + ret->allocated_len = MAX(ret->len + 1, 16); + ret->str = g_malloc(ret->allocated_len); + if (init) + memcpy(ret->str, init, ret->len); + ret->str[ret->len] = 0; + + return ret; +} + +GString * +g_string_new (const gchar *init) +{ + return g_string_new_len(init, -1); +} + +GString * +g_string_sized_new (gsize default_size) +{ + GString *ret = g_new (GString, 1); + + ret->str = g_malloc (default_size); + ret->str [0] = 0; + ret->len = 0; + ret->allocated_len = default_size; + + return ret; +} + +gchar * +g_string_free (GString *string, gboolean free_segment) +{ + gchar *data; + + g_return_val_if_fail (string != NULL, NULL); + + data = string->str; + g_free(string); + + if(!free_segment) { + return data; + } + + g_free(data); + return NULL; +} + +GString * +g_string_append_len (GString *string, const gchar *val, gssize len) +{ + g_return_val_if_fail(string != NULL, NULL); + g_return_val_if_fail(val != NULL, string); + + if(len < 0) { + len = strlen(val); + } + + GROW_IF_NECESSARY(string, len); + memcpy(string->str + string->len, val, len); + string->len += len; + string->str[string->len] = 0; + + return string; +} + +GString * +g_string_append (GString *string, const gchar *val) +{ + g_return_val_if_fail(string != NULL, NULL); + g_return_val_if_fail(val != NULL, string); + + return g_string_append_len(string, val, -1); +} + +GString * +g_string_append_c (GString *string, gchar c) +{ + g_return_val_if_fail(string != NULL, NULL); + + GROW_IF_NECESSARY(string, 1); + + string->str[string->len] = c; + string->str[string->len + 1] = 0; + string->len++; + + return string; +} + +GString * +g_string_prepend (GString *string, const gchar *val) +{ + gssize len; + + g_return_val_if_fail (string != NULL, string); + g_return_val_if_fail (val != NULL, string); + + len = strlen (val); + + GROW_IF_NECESSARY(string, len); + memmove(string->str + len, string->str, string->len + 1); + memcpy(string->str, val, len); + + return string; +} + +GString * +g_string_insert (GString *string, gssize pos, const gchar *val) +{ + gssize len; + + g_return_val_if_fail (string != NULL, string); + g_return_val_if_fail (val != NULL, string); + g_return_val_if_fail (pos <= string->len, string); + + len = strlen (val); + + GROW_IF_NECESSARY(string, len); + memmove(string->str + pos + len, string->str + pos, string->len - pos - len + 1); + memcpy(string->str + pos, val, len); + + return string; +} + +GString * +g_string_truncate (GString *string, gsize len) +{ + g_return_val_if_fail (string != NULL, string); + + /* Silent return */ + if (len >= string->len) + return string; + + string->len = len; + string->str[len] = 0; + return string; +} + +GString * +g_string_set_size (GString *string, gsize len) +{ + g_return_val_if_fail (string != NULL, string); + + GROW_IF_NECESSARY(string, len); + + string->len = len; + string->str[len] = 0; + return string; +} + +GString * +g_string_erase (GString *string, gssize pos, gssize len) +{ + g_return_val_if_fail (string != NULL, string); + + /* Silent return */ + if (pos >= string->len) + return string; + + if (len == -1 || (pos + len) >= string->len) { + string->str[pos] = 0; + } + else { + memmove (string->str + pos, string->str + pos + len, string->len - (pos + len) + 1); + string->len -= len; + } + + return string; +} \ No newline at end of file diff --git a/tests/objc-cli/glib.h b/tests/objc-cli/glib.h new file mode 100644 index 0000000..88d6555 --- /dev/null +++ b/tests/objc-cli/glib.h @@ -0,0 +1,247 @@ +#ifndef __GLIB_H +#define __GLIB_H +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef G_HAVE_ALLOCA_H +#include +#endif + +#ifdef WIN32 +/* For alloca */ +#include +#endif + +#ifndef offsetof +# define offsetof(s_name,n_name) (size_t)(char *)&(((s_name*)0)->m_name) +#endif + +#define __EGLIB_X11 1 + +#ifdef __cplusplus +#define G_BEGIN_DECLS extern "C" { +#define G_END_DECLS } +#else +#define G_BEGIN_DECLS +#define G_END_DECLS +#endif + +G_BEGIN_DECLS + +/* + * Basic data types + */ +typedef int gint; +typedef unsigned int guint; +typedef short gshort; +typedef unsigned short gushort; +typedef long glong; +typedef unsigned long gulong; +typedef void * gpointer; +typedef const void * gconstpointer; +typedef char gchar; +typedef unsigned char guchar; + +/* Types defined in terms of the stdint.h */ +typedef int8_t gint8; +typedef uint8_t guint8; +typedef int16_t gint16; +typedef uint16_t guint16; +typedef int32_t gint32; +typedef uint32_t guint32; +typedef int64_t gint64; +typedef uint64_t guint64; +typedef float gfloat; +typedef double gdouble; +typedef int32_t gboolean; + +typedef guint16 gunichar2; +typedef guint32 gunichar; + +typedef unsigned long gsize; +typedef signed long gssize; + +/* + * Macros + */ +#define G_N_ELEMENTS(s) (sizeof(s) / sizeof ((s) [0])) + +#define FALSE 0 +#define TRUE 1 + +#define G_MINSHORT SHRT_MIN +#define G_MAXSHORT SHRT_MAX +#define G_MAXUSHORT USHRT_MAX +#define G_MAXINT INT_MAX +#define G_MININT INT_MIN +#define G_MAXINT32 INT32_MAX +#define G_MAXUINT32 UINT32_MAX +#define G_MININT32 INT32_MIN +#define G_MININT64 INT64_MIN +#define G_MAXINT64 INT64_MAX +#define G_MAXUINT64 UINT64_MAX + +#define G_LITTLE_ENDIAN 1234 +#define G_BIG_ENDIAN 4321 +#define G_STMT_START do +#define G_STMT_END while (0) + +#define G_USEC_PER_SEC 1000000 + +#ifndef ABS +#define ABS(a) ((a) > 0 ? (a) : -(a)) +#endif + +#define G_STRUCT_OFFSET(p_type,field) offsetof(p_type,field) + +#define EGLIB_STRINGIFY(x) #x +#define EGLIB_TOSTRING(x) EGLIB_STRINGIFY(x) +#define G_STRLOC __FILE__ ":" EGLIB_TOSTRING(__LINE__) ":" + +#define G_CONST_RETURN const + +#define G_GUINT64_FORMAT PRIu64 +#define G_GINT64_FORMAT PRIi64 +#define G_GUINT32_FORMAT PRIu32 +#define G_GINT32_FORMAT PRIi32 + +/* + * Allocation + */ +void g_free (void *ptr); +gpointer g_realloc (gpointer obj, gsize size); +gpointer g_malloc (gsize x); +gpointer g_malloc0 (gsize x); +gpointer g_calloc (gsize n, gsize x); +gpointer g_try_malloc (gsize x); +gpointer g_try_realloc (gpointer obj, gsize size); + +#define g_new(type,size) ((type *) g_malloc (sizeof (type) * (size))) +#define g_new0(type,size) ((type *) g_malloc0 (sizeof (type)* (size))) +#define g_newa(type,size) ((type *) alloca (sizeof (type) * (size))) + +#define g_memmove(dest,src,len) memmove (dest, src, len) +#define g_renew(struct_type, mem, n_structs) g_realloc (mem, sizeof (struct_type) * n_structs) +#define g_alloca(size) alloca (size) + +gpointer g_memdup (gconstpointer mem, guint byte_size); +gchar *g_strdup (const gchar *str); +gchar **g_strdupv (gchar **str_array); + +/* + * Precondition macros + */ +#define g_warn_if_fail(x) G_STMT_START { if (!(x)) { g_warning ("%s:%d: assertion '%s' failed", __FILE__, __LINE__, #x); } } G_STMT_END +#define g_return_if_fail(x) G_STMT_START { if (!(x)) { g_critical ("%s:%d: assertion '%s' failed", __FILE__, __LINE__, #x); return; } } G_STMT_END +#define g_return_val_if_fail(x,e) G_STMT_START { if (!(x)) { g_critical ("%s:%d: assertion '%s' failed", __FILE__, __LINE__, #x); return (e); } } G_STMT_END + +/* + * Array + */ + +typedef struct _GArray GArray; +struct _GArray { + gchar *data; + gint len; +}; + +GArray *g_array_new (gboolean zero_terminated, gboolean clear_, guint element_size); +GArray *g_array_sized_new (gboolean zero_terminated, gboolean clear_, guint element_size, guint reserved_size); +gchar* g_array_free (GArray *array, gboolean free_segment); +GArray *g_array_append_vals (GArray *array, gconstpointer data, guint len); +GArray* g_array_insert_vals (GArray *array, guint index_, gconstpointer data, guint len); +GArray* g_array_remove_index (GArray *array, guint index_); +GArray* g_array_remove_index_fast (GArray *array, guint index_); +void g_array_set_size (GArray *array, gint length); + +#define g_array_append_val(a,v) (g_array_append_vals((a),&(v),1)) +#define g_array_insert_val(a,i,v) (g_array_insert_vals((a),(i),&(v),1)) +#define g_array_index(a,t,i) *(t*)(((a)->data) + sizeof(t) * (i)) + +/* + * String type + */ +typedef struct _GString { + char *str; + gsize len; + gsize allocated_len; +} GString; + +GString *g_string_new (const gchar *init); +GString *g_string_new_len (const gchar *init, gssize len); +GString *g_string_sized_new (gsize default_size); +gchar *g_string_free (GString *string, gboolean free_segment); +GString *g_string_append (GString *string, const gchar *val); +GString *g_string_append_c (GString *string, gchar c); +GString *g_string_append (GString *string, const gchar *val); +GString *g_string_append_len (GString *string, const gchar *val, gssize len); +GString *g_string_truncate (GString *string, gsize len); +GString *g_string_prepend (GString *string, const gchar *val); +GString *g_string_insert (GString *string, gssize pos, const gchar *val); +GString *g_string_set_size (GString *string, gsize len); +GString *g_string_erase (GString *string, gssize pos, gssize len); + +#define g_string_sprintfa g_string_append_printf + +#ifndef MAX +#define MAX(a,b) (((a)>(b)) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a,b) (((a)<(b)) ? (a) : (b)) +#endif + +#ifndef CLAMP +#define CLAMP(a,low,high) (((a) < (low)) ? (low) : (((a) > (high)) ? (high) : (a))) +#endif + +#if defined(_MSC_VER) +#define eg_unreachable() __assume(0) +#elif defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 5))) +#define eg_unreachable() __builtin_unreachable() +#else +#define eg_unreachable() +#endif + +#define g_assert(x) G_STMT_START { if (G_UNLIKELY (!(x))) g_assertion_message ("* Assertion at %s:%d, condition `%s' not met\n", __FILE__, __LINE__, #x); } G_STMT_END +#define g_assert_not_reached() G_STMT_START { g_assertion_message ("* Assertion: should not be reached at %s:%d\n", __FILE__, __LINE__); eg_unreachable(); } G_STMT_END + +#define g_critical(format, ...) + +/* + * Path + */ +#ifdef _MSC_VER +#define G_DIR_SEPARATOR '\\' +#define G_DIR_SEPARATOR_S "\\" +#else +#define G_DIR_SEPARATOR '/' +#define G_DIR_SEPARATOR_S "/" +#endif + +gchar *g_build_path (const gchar *separator, const gchar *first_element, ...); +#define g_build_filename(x, ...) g_build_path(G_DIR_SEPARATOR_S, x, __VA_ARGS__) +gchar *g_path_get_dirname (const gchar *filename); +gchar *g_path_get_basename (const char *filename); +gchar *g_find_program_in_path (const gchar *program); +gchar *g_get_current_dir (void); +gboolean g_path_is_absolute (const char *filename); + +#define _EGLIB_MAJOR 2 +#define _EGLIB_MIDDLE 4 +#define _EGLIB_MINOR 0 + +#define GLIB_CHECK_VERSION(a,b,c) ((a < _EGLIB_MAJOR) || (a == _EGLIB_MAJOR && (b < _EGLIB_MIDDLE || (b == _EGLIB_MIDDLE && c <= _EGLIB_MINOR)))) + +G_END_DECLS + +#endif + + diff --git a/tests/objc-cli/libmanaged.dylib b/tests/objc-cli/libmanaged.dylib new file mode 100755 index 0000000000000000000000000000000000000000..80cbd2a963bd3592aa418f4caf34bab64c6a0e77 GIT binary patch literal 22284 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 literal 0 HcmV?d00001 diff --git a/tests/objc-cli/mono_embeddinator.c b/tests/objc-cli/mono_embeddinator.c new file mode 100644 index 0000000..c49ace6 --- /dev/null +++ b/tests/objc-cli/mono_embeddinator.c @@ -0,0 +1,279 @@ +/* + * Mono managed-to-native support code. + * + * Author: + * Joao Matos (joao.matos@xamarin.com) + * + * (C) 2016 Microsoft, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "mono_embeddinator.h" +#include "glib.h" + +#include +#include +#include +#include + +#if defined(__APPLE__) +#include +#include +#include +#endif + +#if defined(__OBJC__) +#include +#include +#endif + +#ifdef _WIN32 +#include +#endif + +#include +#include +#include +#include + +mono_embeddinator_context_t* _current_context; + +mono_embeddinator_context_t* mono_embeddinator_get_context() +{ + return _current_context; +} + +void mono_embeddinator_set_context(mono_embeddinator_context_t* ctx) +{ + _current_context = ctx; +} + +#if defined(__OBJC__) +id allocAndInitAutoreleasePool() +{ + Class NSAutoreleasePoolClass = objc_getClass("NSAutoreleasePool"); + id pool = class_createInstance(NSAutoreleasePoolClass, 0); + return objc_msgSend(pool, sel_registerName("init")); +} + +void drainAutoreleasePool(id pool) +{ + (void)objc_msgSend(pool, sel_registerName("drain")); +} + +#define AUTORELEASE_POOL_DEFAULT_VALUE ((id)-1) +static id _autoreleasePool = AUTORELEASE_POOL_DEFAULT_VALUE; +#endif + +int mono_embeddinator_init(mono_embeddinator_context_t* ctx, const char* domain) +{ + if (ctx == 0 || ctx->domain != 0) + return false; + + mono_config_parse(NULL); + ctx->domain = mono_jit_init_version(domain, "v4.0.30319"); + + mono_embeddinator_set_context(ctx); + +#if defined(__OBJC__) + if (_autoreleasePool == AUTORELEASE_POOL_DEFAULT_VALUE) + _autoreleasePool = allocAndInitAutoreleasePool(); +#endif + + return true; +} + +int mono_embeddinator_destroy(mono_embeddinator_context_t* ctx) +{ + if (ctx == 0 || ctx->domain != 0) + return false; + + mono_jit_cleanup (ctx->domain); + +#if defined(__OBJC__) + if (_autoreleasePool != AUTORELEASE_POOL_DEFAULT_VALUE) + { + drainAutoreleasePool(_autoreleasePool); + _autoreleasePool = AUTORELEASE_POOL_DEFAULT_VALUE; + } +#endif + + return true; +} + +static GString* get_current_executable_path() +{ +#if defined(__APPLE__) + int ret; + pid_t pid; + char pathbuf[PROC_PIDPATHINFO_MAXSIZE]; + + pid = getpid(); + ret = proc_pidpath (pid, pathbuf, sizeof(pathbuf)); + + return (ret > 0) ? g_string_new(pathbuf) : 0; +#elif defined(_WIN32) + HMODULE hModule = GetModuleHandleW(0); + CHAR pathbuf[MAX_PATH]; + DWORD ret = GetModuleFileNameA(hModule, pathbuf, MAX_PATH); + + return (ret > 0) ? g_string_new(pathbuf) : 0; +#else + g_assert_not_reached(); +#endif +} + +static gchar* +strrchr_seperator (const gchar* filename) +{ +#ifdef G_OS_WIN32 + char *p2; +#endif + char *p; + + p = strrchr (filename, G_DIR_SEPARATOR); +#ifdef G_OS_WIN32 + p2 = strrchr (filename, '/'); + if (p2 > p) + p = p2; +#endif + + return p; +} + +char* mono_embeddinator_search_assembly(const char* assembly) +{ + GString* path = get_current_executable_path(); + + gchar* sep = strrchr_seperator(path->str); + g_string_truncate(path, sep - path->str); + + g_string_append(path, G_DIR_SEPARATOR_S); + g_string_append(path, assembly); + + char* data = path->str; + g_string_free(path, /*free_segment=*/ FALSE); + + return data; +} + +MonoImage* mono_embeddinator_load_assembly(mono_embeddinator_context_t* ctx, const char* assembly) +{ + const char* path = mono_embeddinator_search_assembly(assembly); + MonoAssembly* mono_assembly = mono_domain_assembly_open(ctx->domain, path); + if (mono_assembly == 0) + { + mono_embeddinator_error_t __error; + __error.type = MONO_EMBEDDINATOR_ASSEMBLY_OPEN_FAILED; + __error.string = path; + mono_embeddinator_error(__error); + return 0; + } + + return mono_assembly_get_image(mono_assembly); +} + +static mono_embeddinator_assembly_search_hook_t g_assembly_search_hook = 0; + +void* mono_embeddinator_install_assembly_search_hook(mono_embeddinator_assembly_search_hook_t hook) +{ + mono_embeddinator_assembly_search_hook_t prev = g_assembly_search_hook; + g_assembly_search_hook = hook; + return (void*)prev; +} + +MonoClass* mono_embeddinator_search_class(const char* assembly, const char* _namespace, + const char* name) +{ + mono_embeddinator_context_t* ctx = mono_embeddinator_get_context(); + + const char* path = mono_embeddinator_search_assembly(assembly); + MonoAssembly* mono_assembly = mono_domain_assembly_open(ctx->domain, path); + + if (mono_assembly == 0) + { + mono_embeddinator_error_t error; + error.type = MONO_EMBEDDINATOR_ASSEMBLY_OPEN_FAILED; + error.string = path; + mono_embeddinator_error(error); + } + + MonoImage* image = mono_assembly_get_image(mono_assembly); + MonoClass* klass = mono_class_from_name(image, _namespace, name); + + return klass; +} + +MonoMethod* mono_embeddinator_lookup_method(const char* method_name, MonoClass *klass) +{ + MonoMethodDesc* desc = mono_method_desc_new(method_name, /*include_namespace=*/true); + MonoMethod* method = mono_method_desc_search_in_class(desc, klass); + mono_method_desc_free(desc); + + if (!method) + { + mono_embeddinator_error_t error; + error.type = MONO_EMBEDDINATOR_METHOD_LOOKUP_FAILED; + error.string = method_name; + mono_embeddinator_error(error); + } + + return method; +} + +void mono_embeddinator_throw_exception(MonoObject *exception) +{ + mono_embeddinator_error_t error; + error.type = MONO_EMBEDDINATOR_EXCEPTION_THROWN; + error.exception = (MonoException*) exception; + mono_embeddinator_error(error); +} + +static mono_embeddinator_error_report_hook_t g_error_report_hook = 0; + +void* mono_embeddinator_install_error_report_hook(mono_embeddinator_error_report_hook_t hook) +{ + mono_embeddinator_error_report_hook_t prev = g_error_report_hook; + g_error_report_hook = hook; + return prev; +} + +void mono_embeddinator_error(mono_embeddinator_error_t error) +{ + if (g_error_report_hook == 0) + return; + + g_error_report_hook(error); +} + +void* mono_embeddinator_create_object(MonoObject* instance) +{ + MonoEmbedObject* object = g_new(MonoEmbedObject, 1); + mono_embeddinator_init_object(object, instance); + + return object; +} + +void mono_embeddinator_init_object(MonoEmbedObject* object, MonoObject* instance) +{ + object->_class = mono_object_get_class(instance); + object->_handle = mono_gchandle_new(instance, /*pinned=*/false); +} diff --git a/tests/objc-cli/mono_embeddinator.h b/tests/objc-cli/mono_embeddinator.h new file mode 100644 index 0000000..d7abcf0 --- /dev/null +++ b/tests/objc-cli/mono_embeddinator.h @@ -0,0 +1,222 @@ +/* + * Mono managed-to-native support code. + * + * Author: + * Joao Matos (joao.matos@xamarin.com) + * + * (C) 2016 Microsoft, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#ifdef __cplusplus +#include +#include +#else +#include +#include +#endif + +#ifdef __cplusplus + #define MONO_EMBEDDINATOR_BEGIN_DECLS extern "C" { + #define MONO_EMBEDDINATOR_END_DECLS } +#else + #define MONO_EMBEDDINATOR_BEGIN_DECLS + #define MONO_EMBEDDINATOR_END_DECLS +#endif + +#if defined(_MSC_VER) + #define MONO_EMBEDDINATOR_API_EXPORT __declspec(dllexport) + #define MONO_EMBEDDINATOR_API_IMPORT __declspec(dllimport) +#else + #define MONO_EMBEDDINATOR_API_EXPORT __attribute__ ((visibility ("default"))) + #define MONO_EMBEDDINATOR_API_IMPORT +#endif + +#if defined(MONO_EMBEDDINATOR_DLL_EXPORT) + #define MONO_EMBEDDINATOR_API MONO_EMBEDDINATOR_API_EXPORT +#else + #define MONO_EMBEDDINATOR_API MONO_EMBEDDINATOR_API_IMPORT +#endif + +typedef uint16_t gunichar2; + +typedef struct _GArray GArray; +typedef struct _GString GString; + +typedef struct _MonoDomain MonoDomain; +typedef struct _MonoException MonoException; +typedef struct _MonoClass MonoClass; +typedef struct _MonoObject MonoObject; +typedef struct _MonoImage MonoImage; +typedef struct _MonoMethod MonoMethod; + +MONO_EMBEDDINATOR_BEGIN_DECLS + +/** + * Represents a managed-to-native binding context. + */ +typedef struct +{ + MonoDomain* domain; +} mono_embeddinator_context_t; + +/** + * Initializes a managed-to-native binding context. + * Returns a boolean indicating success or failure. + */ +MONO_EMBEDDINATOR_API +int mono_embeddinator_init(mono_embeddinator_context_t* ctx, const char* domain); + +/** + * Destroys the managed-to-native binding context. + * Returns a boolean indicating success or failure. + */ +MONO_EMBEDDINATOR_API +int mono_embeddinator_destroy(mono_embeddinator_context_t* ctx); + +/** + * Returns the current context. + */ +MONO_EMBEDDINATOR_API +mono_embeddinator_context_t* mono_embeddinator_get_context(); + +/** + * Sets the current context. + */ +MONO_EMBEDDINATOR_API +void mono_embeddinator_set_context(mono_embeddinator_context_t* ctx); + +/** + * Loads an assembly into the context. + */ +MONO_EMBEDDINATOR_API +MonoImage* mono_embeddinator_load_assembly(mono_embeddinator_context_t* ctx, + const char* assembly); + +/** + * Searches and returns the path to the given managed assembly. + */ +MONO_EMBEDDINATOR_API +char* mono_embeddinator_search_assembly(const char* assembly); + +/** Represents the assembly search hook function type. */ +typedef const char* (*mono_embeddinator_assembly_search_hook_t)(const char*); + +/** + * Installs an hook that returns the path to the given managed assembly. + * Returns the previous installed hook. + */ +MONO_EMBEDDINATOR_API +void* mono_embeddinator_install_assembly_search_hook(mono_embeddinator_assembly_search_hook_t hook); + +/** + * Searches and returns for the Mono class in the given assembly. + */ +MONO_EMBEDDINATOR_API +MonoClass* mono_embeddinator_search_class(const char* assembly, const char* _namespace, + const char* name); + +/** + * Looks up and returns a MonoMethod* for a given Mono class and method name. + */ +MONO_EMBEDDINATOR_API +MonoMethod* mono_embeddinator_lookup_method(const char* method_name, MonoClass* klass); + +/** + * Throws an exception based on a given Mono exception object. + */ +MONO_EMBEDDINATOR_API +void mono_embeddinator_throw_exception(MonoObject* exception); + +/** + * Represents the different types of errors to be reported. + */ +typedef enum +{ + MONO_EMBEDDINATOR_OK = 0, + // Mono managed exception + MONO_EMBEDDINATOR_EXCEPTION_THROWN, + // Mono failed to load assembly + MONO_EMBEDDINATOR_ASSEMBLY_OPEN_FAILED, + // Mono failed to lookup method + MONO_EMBEDDINATOR_METHOD_LOOKUP_FAILED +} mono_embeddinator_error_type_t; + +/** + * Represents the error type and associated data. + */ +typedef struct +{ + mono_embeddinator_error_type_t type; + // Contains exception object if type is MONO_EMBEDDINATOR_EXCEPTION_THROWN + MonoException* exception; + const char* string; +} mono_embeddinator_error_t; + +/** + * Fires an error and calls the installed error hook for handling. + */ +MONO_EMBEDDINATOR_API +void mono_embeddinator_error(mono_embeddinator_error_t error); + +/** Represents the error report hook function type. */ +typedef void (*mono_embeddinator_error_report_hook_t)(mono_embeddinator_error_t); + +/** + * Installs an hook that is called for each error reported. + */ +MONO_EMBEDDINATOR_API +void* mono_embeddinator_install_error_report_hook(mono_embeddinator_error_report_hook_t hook); + +/** + * Arrays + */ + +typedef struct +{ + GArray* array; +} MonoEmbedArray; + +/** + * Objects + */ + +typedef struct +{ + MonoClass* _class; + uint32_t _handle; +} MonoEmbedObject; + +/** + * Creates a MonoEmbedObject support object from a Mono object instance. + */ +MONO_EMBEDDINATOR_API +void* mono_embeddinator_create_object(MonoObject* instance); + +/** + * Initializes a MonoEmbedObject object from a Mono object instance. + */ +MONO_EMBEDDINATOR_API +void mono_embeddinator_init_object(MonoEmbedObject* object, MonoObject* instance); + +MONO_EMBEDDINATOR_END_DECLS diff --git a/tests/objc-cli/perf-cli b/tests/objc-cli/perf-cli new file mode 100755 index 0000000000000000000000000000000000000000..15d215a227db03a1548cfceade23312d39a18f4c GIT binary patch literal 8792 zcmeHMU1%It6u#S9jhc2-TczSpx3#JDFB@wM1(EJ1op!3hZcVGDQf_CnlV){yrp(OR zLpPq@C1WIYMtcrP|F~ zTEy9f8%TLfJ8`T%#UJ0*?i0$!+{8LCrsR{9o;m6%10s%B*no$D|Efx%eaCV-jfto! zrR&v-Zp#(N+nx^a9#t8k9S-PFc+2x6o*XeNXH5r5alD+u>r()J=u35Nm(&&hu4MioZl`rfOZs*eM}BXN`GC;RpX4w(#4;5pTg@<18Co_ zZVJyeD~>sgc8=raVtBNp^TV^kvrGzasA9M-5#xAz43Bmc4@hlz%kPna!!N(29XK4m z12VC7g-tr49+oxp*WLFDu^sQJUg{YkSep*W9Arp(Mu<@ubCAp<%ogws*mpx-+9t$B z$a}#BaFm!!j;>QQPJIgFJL68+c+GH1ek@yaoouCC%$CL~CHP1WfjN)4PdEH>@&4V{ zC*Ill;ZswYtvlfJ3)P8VF!;&Ph9se%COD4ou_$p4d_KlF=a6vQs$rq2N+fGpH5{5$6U{>W(Uee$8g572OYd+&e_hJZuX#Evr2|nwymDw(3^eLbX<7c zY=0yUT;lJG;IG;J6JEP1(W(XJ65Oh%FFLdMI3a!oO8YqeQhM^yQ9|rQ7VEZ@3Hsm( zWpkYqN-B_4AgMr7fusUS1^(L#9M|i=>644Sm$iR*r0EeHow3>82Yrfq)+c_e8eHz{IoV-*A_2p4VYqDYdo(lre}uyymcR>n7;Qs zMg4N)EqM1d_cV8;(qCTDhpy|BH%0pVR_4yU@QE+>ehl#yKlt>S_0${uSXclD7u;ZS zE>+hW3-33ZO?`U&T4OU}&(7(S-}RpQw%N^TG`s)suZ#ZmFaNrP>%hz--$3LCo86y7 z&W_+B7JdiN2tgL+sb#2LrM92i6>5^&*U-xDYxw_UpL0dkC|d%58;76qOxNqFifykK zDuy>~JJn1p>s0VP{4j=-qLSZ%{7&2hNq&r_1ySd>c_+TBy1>tPv4$2)e+;|X29es9Fjwf0ENx3XyvjQjE6Q5!0!l%?MpUmmnl#^28 zw9s@s>3Eiy70wp;49_l8&uq>GN1jH_vmLWy8m?Ke?MlHu%kZw%!Zmk<@!l|AbW={on3y%tudFITsXP!ZJfI+!i#WFbI iUHQz?f96$IvVD1ig;{k;ZXMua1d(tVRy0O1XYntrH_;{l literal 0 HcmV?d00001 diff --git a/tests/objc-cli/perf-test.m b/tests/objc-cli/perf-test.m new file mode 100644 index 0000000..e052185 --- /dev/null +++ b/tests/objc-cli/perf-test.m @@ -0,0 +1,15 @@ +#import +#include "mono_embeddinator.h" +#include "bindings.h" + +int main (int argc, const char * argv[]) +{ + @autoreleasepool { + int counter = argc == 1 ? 1000000 : atoi (argv [0]); + + for (int i = 0; i < counter; i++) { + assert (![Platform isWindows]); + } + } + return 0; +} diff --git a/tests/objc-cli/test-cli b/tests/objc-cli/test-cli new file mode 100755 index 0000000000000000000000000000000000000000..da28713ca7eb54266222729ec5b36a63a374b5e0 GIT binary patch literal 8824 zcmeHNUuYaf7@te4MopS)t0hvk*VvROAs0&`MF`&Ia`9@9_S%boYnbfa&E?MA?H;>( zCV40Xq7NYi4}{`NK`5w?d9W`+p`c&{q2Pmvh~z=#0t!V6{y}?wzunopz0IG#__$w~ zo%#OEZ@&HJ+s*9E-TM2tyALoH*vHsX2V?9ol?n;oWg%)Y_864}70y%97vpclFP?|A zodWIbjvR0XXaLTq;;&7$n^^sW?J_2La)sST<$kH=+!PCD%hrpx*-bY?>c6B3`28(& zFiUQhbHl7=jHbwo_x%AIuUA?)ywjmm;v(QWo3%dtc&(BnWsnZO5ys^F=ksi)vmY zL$80IN<8Ec2)q}=*4Wopo=iliqAm^PLtCCW`QpkG%3)WYs3mSJmNQz3S4^G!+8NJ* zLB65CLzqu@-f&)0_QDHNfA|-Y0N~wt$YUo*V8VGe@19t%f5Q@Q2F66--FUXNb(Qm4 zEGx4DQ{ly{NxV+k1^iy~An^=Q(nX#g4=>&a63=-qz`OmUXO<)_l6cvYVi-X5;;lbyDIrgu5D!|AH;Z|&^2m}h)<^HXVYEZ`070q?;3X}D z7@MK?cT~d;Fu3R7amF5`dV}h9svoA3qT(jlqF~J3=tJuN&<;v^Ex;w#MI~G{^l+(| z3Fj6|IpRS_slbox7jA6Uj*NW0Tpv68&gC1|PLM1}g>?}sm1i6tGNJ*xU-ZL!(M=c! z_Xiz(c8G>8D=H;bZiq%NW*j-}XQ(voUx?F`4+g^NMZ*;3aI%=u6@4*0snc6#Ueo7{ z@T68%bBbBi)SFlB_U4oiy*r^`|9|eDcYUfFA)r z0)7Pi2>f3Wcsa51b7J||;Fs}#09pT?E{WCd>-0Z9u{wGM)yl2JO8j>HM`+f%k3zII z`dk3j*Z@_Z1QI>*KgevI)jzhozioHtcK7-k56^6fglRi3?>SpFh7{duj? zKTI7P{im$!h;_wXF_v6=qMI7gbff=YVr$lVZ|j#vqfx-BXzK^G2GRNkEx56@L9Kox zWSF#o$%ZPrMxS@)VrW*FrqDy0T3Te6CZlJP)9g|znodu%U5$6r7&c6{AhL6;XuL`v zRNB13#6r=GX*t12AD8Xt?e**9jkR>v>y|V6;wPU*>7q!m!=aY^?){g#l*$?Y=H#vGk>W{gU5o$Z%p;x8;BhUCQbHC|F zz>k0*0Y3tM1pEm25%446N5GGO9|1oCegymo+#>=9`+`&Bm0tP_reS(8!q1Pt6yvcZ z?PBl~JXKQ6yr!4g1${kGI~>6glyzjzGqg!TN8C#rcWG+`6sSEC;he`NV|1QlDyo^b z4z6Q3^1CSVLKkXQu%&^U9lbTC2M-20D1Tz{P^dR!u=?@(LV2URH`K>&IrvKDLQ-G?3GP zxF=wppjkU5M=ajnSHXq}_FJfinMF_0mH6gf3T@ATp|dKR-n4oAgu$XJT}j{M-}CU; z-XcA=Yb?S*Fvi(2wp?&#L=^GLLv%vB{a(3suQJZNOzgd +#include "mono_embeddinator.h" +#include "bindings.h" + +int main () +{ + @autoreleasepool { + NSLog (@"%s static property getter only", [Platform isWindows] ? "[FAIL]" : "[PASS]"); + + NSLog (@"%s static property getter", [Platform exitCode] == 0 ? "[PASS]" : "[FAIL]"); + Platform.exitCode = 255; + NSLog (@"%s static property setter check", [Platform exitCode] == 255 ? "[PASS]" : "[FAIL]"); + } + return 0; +} diff --git a/tests/objcgentest/ObjCGeneratorTest.cs b/tests/objcgentest/ObjCGeneratorTest.cs new file mode 100644 index 0000000..f008f30 --- /dev/null +++ b/tests/objcgentest/ObjCGeneratorTest.cs @@ -0,0 +1,27 @@ +using NUnit.Framework; +using System; +using ObjC; + +namespace ObjCGeneratorTest { + + [TestFixture] + public class Helpers { + + [Test] + public void CamelCase () + { + Assert.Null (ObjCGenerator.CamelCase (null), "null"); + Assert.That (ObjCGenerator.CamelCase (String.Empty), Is.EqualTo (""), "length == 0"); + Assert.That (ObjCGenerator.CamelCase ("S"), Is.EqualTo ("s"), "length == 1"); + Assert.That (ObjCGenerator.CamelCase ("TU"), Is.EqualTo ("tU"), "length == 2"); + } + + [Test] + public void TypeMatch () + { + Assert.That (ObjCGenerator.GetTypeName (typeof (bool)), Is.EqualTo ("bool"), "bool"); + Assert.That (ObjCGenerator.GetTypeName (typeof (int)), Is.EqualTo ("int"), "int"); + Assert.That (ObjCGenerator.GetTypeName (typeof (object)), Is.EqualTo ("NSObject"), "object"); + } + } +} diff --git a/tests/objcgentest/objcgentest.csproj b/tests/objcgentest/objcgentest.csproj new file mode 100644 index 0000000..bed7cfa --- /dev/null +++ b/tests/objcgentest/objcgentest.csproj @@ -0,0 +1,46 @@ + + + + Debug + AnyCPU + {076A871B-0C13-47D8-8923-B9242995BFF8} + Library + objcgentest + objcgentest + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + + + true + bin\Release + prompt + 4 + + + + + ..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll + + + + + + + + + + + {C166803B-011F-4EAF-B8C2-D7DBBA3CF1EC} + objcgen + + + + \ No newline at end of file