617 строки
21 KiB
C#
617 строки
21 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
using IKVM.Reflection;
|
|
using Type = IKVM.Reflection.Type;
|
|
|
|
using Embeddinator;
|
|
|
|
namespace ObjC {
|
|
|
|
public class ObjCGenerator : Generator {
|
|
|
|
static TextWriter headers = new StringWriter ();
|
|
static TextWriter implementation = new StringWriter ();
|
|
|
|
static ParameterInfo [] NoParameters = new ParameterInfo [0];
|
|
|
|
List<Type> types = new List<Type> ();
|
|
Dictionary<Type, List<ConstructorInfo>> ctors = new Dictionary<Type, List<ConstructorInfo>> ();
|
|
Dictionary<Type, List<MethodInfo>> methods = new Dictionary<Type, List<MethodInfo>> ();
|
|
Dictionary<Type, List<PropertyInfo>> properties = new Dictionary<Type, List<PropertyInfo>> ();
|
|
|
|
public override void Process (IEnumerable<Assembly> assemblies)
|
|
{
|
|
foreach (var a in assemblies) {
|
|
foreach (var t in a.GetTypes ()) {
|
|
if (!t.IsPublic)
|
|
continue;
|
|
// gather types for forward declarations
|
|
types.Add (t);
|
|
|
|
var constructors = new List<ConstructorInfo> ();
|
|
foreach (var ctor in t.GetConstructors ()) {
|
|
// .cctor not to be called directly by native code
|
|
if (ctor.IsStatic)
|
|
continue;
|
|
if (!ctor.IsPublic)
|
|
continue;
|
|
constructors.Add (ctor);
|
|
}
|
|
constructors = constructors.OrderBy ((arg) => arg.ParameterCount).ToList ();
|
|
ctors.Add (t, constructors);
|
|
|
|
var meths = new List<MethodInfo> ();
|
|
foreach (var mi in t.GetMethods (BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) {
|
|
meths.Add (mi);
|
|
}
|
|
methods.Add (t, meths);
|
|
|
|
var props = new List<PropertyInfo> ();
|
|
foreach (var pi in t.GetProperties (BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) {
|
|
var getter = pi.GetGetMethod ();
|
|
var setter = pi.GetSetMethod ();
|
|
// setter only property are valid in .NET and we need to generate a method in ObjC (there's no writeonly properties)
|
|
if (getter == null)
|
|
continue;
|
|
// we can do better than methods for the more common cases (readonly and readwrite)
|
|
meths.Remove (getter);
|
|
meths.Remove (setter);
|
|
props.Add (pi);
|
|
}
|
|
props = props.OrderBy ((arg) => arg.Name).ToList ();
|
|
properties.Add (t, props);
|
|
}
|
|
}
|
|
types = types.OrderBy ((arg) => arg.FullName).OrderBy ((arg) => types.Contains (arg.BaseType)).ToList ();
|
|
Console.WriteLine ($"\t{types.Count} types found");
|
|
}
|
|
|
|
public override void Generate (IEnumerable<Assembly> assemblies)
|
|
{
|
|
headers.WriteLine ("#include \"mono_embeddinator.h\"");
|
|
headers.WriteLine ("#import <Foundation/Foundation.h>");
|
|
headers.WriteLine ();
|
|
headers.WriteLine ();
|
|
headers.WriteLine ("#if !__has_feature(objc_arc)");
|
|
headers.WriteLine ("#error Embeddinator code must be built with ARC.");
|
|
headers.WriteLine ("#endif");
|
|
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 \"objc-support.h\"");
|
|
implementation.WriteLine ("#include <mono/jit/jit.h>");
|
|
implementation.WriteLine ("#include <mono/metadata/assembly.h>");
|
|
implementation.WriteLine ("#include <mono/metadata/object.h>");
|
|
implementation.WriteLine ("#include <mono/metadata/mono-config.h>");
|
|
implementation.WriteLine ("#include <mono/metadata/debug-helpers.h>");
|
|
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* {GetObjCName (t)}_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__initialize_mono ();");
|
|
implementation.WriteLine ($"\t__{name}_image = mono_embeddinator_load_assembly (&__mono_context, \"{name}.dll\");");
|
|
implementation.WriteLine ($"\tassert (__{name}_image && \"Could not load the assembly '{name}.dll'.\");");
|
|
implementation.WriteLine ("}");
|
|
implementation.WriteLine ();
|
|
|
|
foreach (var t in types) {
|
|
Generate (t);
|
|
}
|
|
}
|
|
|
|
protected override void Generate (Type t)
|
|
{
|
|
var has_bound_base_class = types.Contains (t.BaseType);
|
|
var static_type = t.IsSealed && t.IsAbstract;
|
|
|
|
var managed_name = GetObjCName (t);
|
|
|
|
var native_name = GetTypeName (t);
|
|
headers.WriteLine ();
|
|
headers.WriteLine ($"// {t.AssemblyQualifiedName}");
|
|
headers.WriteLine ($"@interface {native_name} : {GetTypeName (t.BaseType)} {{");
|
|
if (!static_type && !has_bound_base_class) {
|
|
headers.WriteLine ("\tMonoEmbedObject* _object;");
|
|
}
|
|
headers.WriteLine ("}");
|
|
headers.WriteLine ();
|
|
|
|
implementation.WriteLine ();
|
|
implementation.WriteLine ($"// {t.AssemblyQualifiedName}");
|
|
implementation.WriteLine ($"@implementation {native_name} {{");
|
|
// our internal field is only needed once in the type hierarchy
|
|
implementation.WriteLine ("}");
|
|
implementation.WriteLine ();
|
|
|
|
implementation.WriteLine ("+ (void) initialize");
|
|
implementation.WriteLine ("{");
|
|
implementation.WriteLine ($"\tif (self != [{managed_name} class])");
|
|
implementation.WriteLine ("\t\treturn;");
|
|
var aname = t.Assembly.GetName ().Name;
|
|
implementation.WriteLine ($"\t__lookup_assembly_{aname} ();");
|
|
|
|
implementation.WriteLine ("#if TOKENLOOKUP");
|
|
implementation.WriteLine ($"\t{managed_name}_class = mono_class_get (__{aname}_image, 0x{t.MetadataToken:X8});");
|
|
implementation.WriteLine ("#else");
|
|
implementation.WriteLine ($"\t{managed_name}_class = mono_class_from_name (__{aname}_image, \"{t.Namespace}\", \"{t.Name}\");");
|
|
implementation.WriteLine ("#endif");
|
|
implementation.WriteLine ("}");
|
|
implementation.WriteLine ();
|
|
|
|
if (!static_type && !has_bound_base_class) {
|
|
implementation.WriteLine ("-(void) dealloc");
|
|
implementation.WriteLine ("{");
|
|
implementation.WriteLine ("\tif (_object)");
|
|
implementation.WriteLine ("\t\tmono_embeddinator_destroy_object (_object);");
|
|
implementation.WriteLine ("}");
|
|
implementation.WriteLine ("");
|
|
}
|
|
|
|
var default_init = false;
|
|
List<ConstructorInfo> constructors;
|
|
if (ctors.TryGetValue (t, out constructors)) {
|
|
foreach (var ctor in constructors) {
|
|
var pcount = ctor.ParameterCount;
|
|
default_init |= pcount == 0;
|
|
|
|
var parameters = ctor.GetParameters ();
|
|
StringBuilder name = new StringBuilder ("init");
|
|
foreach (var p in parameters) {
|
|
if (name.Length == 4)
|
|
name.Append ("With");
|
|
else
|
|
name.Append (' ');
|
|
name.Append (PascalCase (p.Name));
|
|
name.Append (":(").Append (GetTypeName (p.ParameterType)).Append (") ").Append (p.Name);
|
|
}
|
|
|
|
var signature = new StringBuilder (".ctor(");
|
|
foreach (var p in parameters) {
|
|
if (signature.Length > 6)
|
|
signature.Append (',');
|
|
signature.Append (GetMonoName (p.ParameterType));
|
|
}
|
|
signature.Append (")");
|
|
|
|
headers.WriteLine ($"- (instancetype){name};");
|
|
|
|
implementation.WriteLine ($"- (instancetype){name}");
|
|
implementation.WriteLine ("{");
|
|
implementation.WriteLine ("\tstatic MonoMethod* __method = nil;");
|
|
implementation.WriteLine ("\tif (!__method) {");
|
|
implementation.WriteLine ("#if TOKENLOOKUP");
|
|
implementation.WriteLine ($"\t\t__method = mono_get_method (__{aname}_image, 0x{ctor.MetadataToken:X8}, {managed_name}_class);");
|
|
implementation.WriteLine ("#else");
|
|
implementation.WriteLine ($"\t\tconst char __method_name [] = \"{t.FullName}:{signature}\";");
|
|
implementation.WriteLine ($"\t\t__method = mono_embeddinator_lookup_method (__method_name, {managed_name}_class);");
|
|
implementation.WriteLine ("#endif");
|
|
implementation.WriteLine ("\t}");
|
|
// TODO: this logic will need to be update for managed NSObject types (e.g. from XI / XM) not to call [super init]
|
|
implementation.WriteLine ("\tif (!_object) {");
|
|
implementation.WriteLine ($"\t\tMonoObject* __instance = mono_object_new (__mono_context.domain, {managed_name}_class);");
|
|
implementation.WriteLine ("\t\tMonoObject* __exception = nil;");
|
|
var args = "nil";
|
|
if (pcount > 0) {
|
|
implementation.WriteLine ($"\t\tvoid* __args [{pcount}];");
|
|
for (int i = 0; i < pcount; i++) {
|
|
var p = parameters [i];
|
|
switch (Type.GetTypeCode (p.ParameterType)) {
|
|
case TypeCode.String:
|
|
implementation.WriteLine ($"\t\t__args [{i}] = mono_string_new (__mono_context.domain, [{p.Name} UTF8String]);");
|
|
break;
|
|
case TypeCode.Boolean:
|
|
case TypeCode.Char:
|
|
case TypeCode.SByte:
|
|
case TypeCode.Int16:
|
|
case TypeCode.Int32:
|
|
case TypeCode.Int64:
|
|
case TypeCode.Byte:
|
|
case TypeCode.UInt16:
|
|
case TypeCode.UInt32:
|
|
case TypeCode.UInt64:
|
|
case TypeCode.Single:
|
|
case TypeCode.Double:
|
|
implementation.WriteLine ($"\t\t__args [{i}] = &{p.Name};");
|
|
break;
|
|
default:
|
|
throw new NotImplementedException ($"Converting type {p.ParameterType.FullName} to mono code");
|
|
}
|
|
}
|
|
args = "__args";
|
|
}
|
|
implementation.WriteLine ($"\t\tmono_runtime_invoke (__method, __instance, {args}, &__exception);");
|
|
implementation.WriteLine ("\t\tif (__exception)");
|
|
// TODO: Apple often do NSLog (or asserts but they are more brutal) and returning nil is allowed (and common)
|
|
implementation.WriteLine ("\t\t\treturn nil;");
|
|
//implementation.WriteLine ("\t\t\tmono_embeddinator_throw_exception (__exception);");
|
|
implementation.WriteLine ("\t\t_object = mono_embeddinator_create_object (__instance);");
|
|
implementation.WriteLine ("\t}");
|
|
if (types.Contains (t.BaseType))
|
|
implementation.WriteLine ("\treturn self = [super initForSuper];");
|
|
else
|
|
implementation.WriteLine ("\treturn self = [super init];");
|
|
implementation.WriteLine ("}");
|
|
implementation.WriteLine ();
|
|
}
|
|
}
|
|
|
|
if (!default_init || static_type) {
|
|
if (static_type)
|
|
headers.WriteLine ("// a .net static type cannot be initialized");
|
|
headers.WriteLine ("- (instancetype)init NS_UNAVAILABLE;");
|
|
}
|
|
|
|
// TODO we should re-use the base `init` when it exists
|
|
if (!static_type) {
|
|
headers.WriteLine ("- (instancetype)initForSuper;");
|
|
|
|
implementation.WriteLine ("// only when `init` is not generated and we have subclasses");
|
|
implementation.WriteLine ("- (instancetype) initForSuper {");
|
|
// calls super's initForSuper until we reach a non-generated type
|
|
if (types.Contains (t.BaseType))
|
|
implementation.WriteLine ("\treturn self = [super initForSuper];");
|
|
else
|
|
implementation.WriteLine ("\treturn self = [super init];");
|
|
implementation.WriteLine ("}");
|
|
implementation.WriteLine ();
|
|
}
|
|
|
|
headers.WriteLine ();
|
|
List<PropertyInfo> props;
|
|
if (properties.TryGetValue (t, out props)) {
|
|
foreach (var pi in props)
|
|
Generate (pi);
|
|
headers.WriteLine ();
|
|
}
|
|
|
|
headers.WriteLine ();
|
|
List<MethodInfo> meths;
|
|
if (methods.TryGetValue (t, out meths)) {
|
|
foreach (var mi in meths)
|
|
Generate (mi);
|
|
headers.WriteLine ();
|
|
}
|
|
|
|
headers.WriteLine ("@end");
|
|
headers.WriteLine ();
|
|
|
|
implementation.WriteLine ("@end");
|
|
implementation.WriteLine ();
|
|
}
|
|
|
|
protected override void Generate (PropertyInfo pi)
|
|
{
|
|
var getter = pi.GetGetMethod ();
|
|
var setter = pi.GetSetMethod ();
|
|
// setter-only properties are handled as methods (and should not reach this code)
|
|
if (getter == null && setter != null)
|
|
throw new EmbeddinatorException (99, "Internal error `setter only`. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues");
|
|
|
|
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};");
|
|
|
|
ImplementMethod (getter.IsStatic, getter.ReturnType, name, NoParameters, pi.DeclaringType, getter.Name, getter.MetadataToken);
|
|
if (setter == null)
|
|
return;
|
|
|
|
ImplementMethod (setter.IsStatic, setter.ReturnType, "set" + pi.Name, setter.GetParameters (), pi.DeclaringType, setter.Name, setter.MetadataToken);
|
|
}
|
|
|
|
public string GetReturnType (Type declaringType, Type returnType)
|
|
{
|
|
if (declaringType == returnType)
|
|
return "instancetype";
|
|
|
|
var return_type = GetTypeName (returnType);
|
|
if (types.Contains (returnType))
|
|
return_type += "*";
|
|
return return_type;
|
|
}
|
|
|
|
// TODO override with attribute ? e.g. [ObjC.Selector ("foo")]
|
|
void ImplementMethod (bool isStatic, Type returnType, string name, ParameterInfo [] parametersInfo, Type type, string managed_name, int token)
|
|
{
|
|
var managed_type_name = GetObjCName (type);
|
|
var return_type = GetReturnType (type, returnType);
|
|
StringBuilder parameters = new StringBuilder ();
|
|
StringBuilder managed_parameters = new StringBuilder ();
|
|
foreach (var p in parametersInfo) {
|
|
if (parameters.Length > 0) {
|
|
parameters.Append (' ');
|
|
managed_parameters.Append (' ');
|
|
}
|
|
parameters.Append (":(").Append (GetTypeName (p.ParameterType)).Append (")").Append (p.Name);
|
|
managed_parameters.Append (GetMonoName (p.ParameterType));
|
|
}
|
|
|
|
implementation.Write (isStatic ? '+' : '-');
|
|
implementation.WriteLine ($" ({return_type}) {name}{parameters}");
|
|
implementation.WriteLine ("{");
|
|
implementation.WriteLine ("\tstatic MonoMethod* __method = nil;");
|
|
implementation.WriteLine ("\tif (!__method) {");
|
|
implementation.WriteLine ("#if TOKENLOOKUP");
|
|
var aname = type.Assembly.GetName ().Name;
|
|
implementation.WriteLine ($"\t\t__method = mono_get_method (__{aname}_image, 0x{token:X8}, {managed_type_name}_class);");
|
|
implementation.WriteLine ("#else");
|
|
implementation.WriteLine ($"\t\tconst char __method_name [] = \"{type.FullName}:{managed_name}({managed_parameters})\";");
|
|
implementation.WriteLine ($"\t\t__method = mono_embeddinator_lookup_method (__method_name, {managed_type_name}_class);");
|
|
implementation.WriteLine ("#endif");
|
|
implementation.WriteLine ("\t}");
|
|
|
|
var args = "nil";
|
|
if (parametersInfo.Length > 0) {
|
|
args = "__args";
|
|
implementation.WriteLine ($"\tvoid* __args [{parametersInfo.Length}];");
|
|
for (int i = 0; i < parametersInfo.Length; i++) {
|
|
implementation.WriteLine ($"\t__args [{i}] = &{parametersInfo [i].Name};");
|
|
}
|
|
}
|
|
|
|
implementation.WriteLine ("\tMonoObject* __exception = nil;");
|
|
var instance = "nil";
|
|
if (!isStatic) {
|
|
implementation.WriteLine ($"\tMonoObject* instance = mono_gchandle_get_target (_object->_handle);");
|
|
instance = "instance";
|
|
}
|
|
|
|
implementation.Write ("\t");
|
|
if (!IsVoid (returnType))
|
|
implementation.Write ("MonoObject* __result = ");
|
|
implementation.WriteLine ($"mono_runtime_invoke (__method, {instance}, {args}, &__exception);");
|
|
|
|
implementation.WriteLine ("\tif (__exception)");
|
|
implementation.WriteLine ("\t\tmono_embeddinator_throw_exception (__exception);");
|
|
ReturnValue (returnType);
|
|
implementation.WriteLine ("}");
|
|
implementation.WriteLine ();
|
|
}
|
|
|
|
public static bool IsVoid (Type t)
|
|
{
|
|
if (t.Name != "Void")
|
|
return false;
|
|
return (t.Namespace == "System");
|
|
}
|
|
|
|
protected override void Generate (MethodInfo mi)
|
|
{
|
|
StringBuilder parameters = new StringBuilder ();
|
|
foreach (var p in mi.GetParameters ()) {
|
|
if (parameters.Length > 0)
|
|
parameters.Append (' ');
|
|
parameters.Append (":(").Append (GetTypeName (p.ParameterType)).Append (")").Append (p.Name);
|
|
}
|
|
|
|
var return_type = GetReturnType (mi.DeclaringType, mi.ReturnType);
|
|
var name = CamelCase (mi.Name);
|
|
|
|
headers.Write (mi.IsStatic ? '+' : '-');
|
|
headers.WriteLine ($" ({return_type}){name}{parameters};");
|
|
|
|
ImplementMethod (mi.IsStatic, mi.ReturnType, name, mi.GetParameters (), mi.DeclaringType, mi.Name, mi.MetadataToken);
|
|
}
|
|
|
|
void ReturnValue (Type t)
|
|
{
|
|
switch (Type.GetTypeCode (t)) {
|
|
case TypeCode.String:
|
|
implementation.WriteLine ("\treturn mono_embeddinator_get_nsstring ((MonoString *) __result);");
|
|
break;
|
|
case TypeCode.Boolean:
|
|
case TypeCode.Char:
|
|
case TypeCode.SByte:
|
|
case TypeCode.Int16:
|
|
case TypeCode.Int32:
|
|
case TypeCode.Int64:
|
|
case TypeCode.Byte:
|
|
case TypeCode.UInt16:
|
|
case TypeCode.UInt32:
|
|
case TypeCode.UInt64:
|
|
case TypeCode.Single:
|
|
case TypeCode.Double:
|
|
var name = GetTypeName (t);
|
|
implementation.WriteLine ("\tvoid* __unbox = mono_object_unbox (__result);");
|
|
implementation.WriteLine ($"\treturn *(({name}*)__unbox);");
|
|
break;
|
|
case TypeCode.Object:
|
|
if (t.Namespace == "System" && t.Name == "Void")
|
|
return;
|
|
if (!types.Contains (t))
|
|
goto default;
|
|
// TODO: cheating by reusing `initForSuper` - maybe a better name is needed
|
|
implementation.WriteLine ($"\t{GetTypeName (t)}* __peer = [[{GetTypeName (t)} alloc] initForSuper];");
|
|
implementation.WriteLine ("\t__peer->_object = mono_embeddinator_create_object (__result);");
|
|
implementation.WriteLine ("\treturn __peer;");
|
|
break;
|
|
default:
|
|
throw new NotImplementedException ($"Returning type {t.Name} from native code");
|
|
}
|
|
}
|
|
|
|
void WriteFile (string name, string content)
|
|
{
|
|
Console.WriteLine ($"\tGenerated: {name}");
|
|
File.WriteAllText (name, content);
|
|
}
|
|
|
|
public override void Write (string outputDirectory)
|
|
{
|
|
WriteFile (Path.Combine (outputDirectory, "bindings.h"), headers.ToString ());
|
|
WriteFile (Path.Combine (outputDirectory, "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:
|
|
switch (t.Namespace) {
|
|
case "System":
|
|
switch (t.Name) {
|
|
case "Object":
|
|
return "NSObject";
|
|
case "Void":
|
|
return "void";
|
|
default:
|
|
return GetObjCName (t);
|
|
}
|
|
default:
|
|
return GetObjCName (t);
|
|
}
|
|
case TypeCode.Boolean:
|
|
return "bool";
|
|
case TypeCode.Char:
|
|
return "unsigned short";
|
|
case TypeCode.Double:
|
|
return "double";
|
|
case TypeCode.Single:
|
|
return "float";
|
|
case TypeCode.Byte:
|
|
return "unsigned char";
|
|
case TypeCode.SByte:
|
|
return "signed char";
|
|
case TypeCode.Int16:
|
|
return "short";
|
|
case TypeCode.Int32:
|
|
return "int";
|
|
case TypeCode.Int64:
|
|
return "long long";
|
|
case TypeCode.UInt16:
|
|
return "unsigned short";
|
|
case TypeCode.UInt32:
|
|
return "unsigned int";
|
|
case TypeCode.UInt64:
|
|
return "unsigned long long";
|
|
case TypeCode.String:
|
|
return "NSString*";
|
|
default:
|
|
throw new NotImplementedException ($"Converting type {t.Name} to a native type name");
|
|
}
|
|
}
|
|
|
|
public static string GetMonoName (Type t)
|
|
{
|
|
switch (Type.GetTypeCode (t)) {
|
|
case TypeCode.Object:
|
|
switch (t.Namespace) {
|
|
case "System":
|
|
switch (t.Name) {
|
|
case "Object":
|
|
return "object";
|
|
case "Void":
|
|
return "void";
|
|
default:
|
|
throw new NotImplementedException ($"Converting type {t.Name} to a mono type name");
|
|
}
|
|
default:
|
|
throw new NotImplementedException ($"Converting type {t.Name} to a mono type name");
|
|
}
|
|
case TypeCode.Boolean:
|
|
return "bool";
|
|
case TypeCode.Char:
|
|
return "char";
|
|
case TypeCode.Double:
|
|
return "double";
|
|
case TypeCode.Single:
|
|
return "single";
|
|
case TypeCode.Byte:
|
|
return "byte";
|
|
case TypeCode.SByte:
|
|
return "sbyte";
|
|
case TypeCode.Int16:
|
|
return "int16";
|
|
case TypeCode.Int32:
|
|
return "int";
|
|
case TypeCode.Int64:
|
|
return "long";
|
|
case TypeCode.UInt16:
|
|
return "uint16";
|
|
case TypeCode.UInt32:
|
|
return "uint";
|
|
case TypeCode.UInt64:
|
|
return "ulong";
|
|
case TypeCode.String:
|
|
return "string";
|
|
default:
|
|
throw new NotImplementedException ($"Converting type {t.Name} to a mono type name");
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
public static string PascalCase (string s)
|
|
{
|
|
if (s == null)
|
|
return null;
|
|
if (s.Length == 0)
|
|
return String.Empty;
|
|
return Char.ToUpperInvariant (s [0]) + s.Substring (1, s.Length - 1);
|
|
}
|
|
|
|
// get a name that is safe to use from ObjC code
|
|
public static string GetObjCName (Type t)
|
|
{
|
|
return t.FullName.Replace ('.', '_');
|
|
}
|
|
}
|
|
}
|