diff --git a/src/Mono.Cxxi/Abi/CppAbi.cs b/src/Mono.Cxxi/Abi/CppAbi.cs deleted file mode 100644 index 20000cd8..00000000 --- a/src/Mono.Cxxi/Abi/CppAbi.cs +++ /dev/null @@ -1,976 +0,0 @@ -// -// Mono.Cxxi.Abi.CppAbi.cs: Represents an abstract C++ ABI -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// -// Copyright (C) 2010-2011 Alexander Corrado -// Copyright 2011 Xamarin Inc (http://www.xamarin.com) -// -// 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. - -using System; -using System.Linq; -using System.Reflection; -using System.Reflection.Emit; - -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Diagnostics; - -using Mono.Cxxi.Util; - -namespace Mono.Cxxi.Abi { - - //FIXME: Exception handling, operator overloading etc. - //FIXME: Allow interface to override default calling convention - - // Subclasses should be singletons - public abstract partial class CppAbi { - // (other part of this partial class in Attributes.cs) - - protected Dictionary wrapper_to_typeinfo = new Dictionary (); - protected MemberFilter vtable_override_filter = VTable.BindToSignatureAndAttribute; - - // Cache some frequently used methodinfos: - protected static readonly MethodInfo typeinfo_nativesize = typeof (CppTypeInfo).GetProperty ("NativeSize").GetGetMethod (); - protected static readonly MethodInfo typeinfo_vtable = typeof (CppTypeInfo).GetProperty ("VTable").GetGetMethod (); - protected static readonly MethodInfo typeinfo_adjvcall = typeof (CppTypeInfo).GetMethod ("GetAdjustedVirtualCall"); - protected static readonly MethodInfo typeinfo_fieldoffset = typeof (CppTypeInfo).GetProperty ("FieldOffsetPadding").GetGetMethod (); - protected static readonly MethodInfo vtable_initinstance = typeof (VTable).GetMethod ("InitInstance"); - protected static readonly MethodInfo vtable_resetinstance = typeof (VTable).GetMethod ("ResetInstance"); - protected static readonly MethodInfo cppobj_native = typeof (ICppObject).GetProperty ("Native").GetGetMethod (); - protected static readonly MethodInfo cppip_native = typeof (CppInstancePtr).GetProperty ("Native").GetGetMethod (); - protected static readonly MethodInfo cppip_managedalloc = typeof (CppInstancePtr).GetProperty ("IsManagedAlloc").GetGetMethod (); - protected static readonly MethodInfo cppip_tomanaged = typeof (CppInstancePtr).GetMethod ("ToManaged", BindingFlags.Static | BindingFlags.NonPublic, null, new Type [] { typeof (IntPtr) }, null); - protected static readonly MethodInfo cppip_tomanaged_size = typeof (CppInstancePtr).GetMethod ("ToManaged", BindingFlags.Static | BindingFlags.NonPublic, null, new Type [] { typeof (IntPtr), typeof (int) }, null); - protected static readonly MethodInfo cppip_dispose = typeof (CppInstancePtr).GetMethod ("Dispose"); - protected static readonly ConstructorInfo cppip_fromnative = typeof (CppInstancePtr).GetConstructor (new Type [] { typeof (IntPtr) }); - protected static readonly ConstructorInfo cppip_fromsize = typeof (CppInstancePtr).GetConstructor (BindingFlags.Instance | BindingFlags.NonPublic, null, new Type [] { typeof (int) }, null); - protected static readonly ConstructorInfo cppip_fromtype_managed = typeof (CppInstancePtr).GetConstructor (BindingFlags.Instance | BindingFlags.NonPublic, null, - new Type[] { typeof (CppTypeInfo), typeof (object) }, null); - protected static readonly ConstructorInfo notimplementedexception = typeof (NotImplementedException).GetConstructor (new Type [] { typeof (string) }); - protected static readonly MethodInfo type_gettypefromhandle = typeof (Type).GetMethod ("GetTypeFromHandle"); - protected static readonly MethodInfo marshal_offsetof = typeof (Marshal).GetMethod ("OffsetOf"); - protected static readonly MethodInfo marshal_structuretoptr = typeof (Marshal).GetMethod ("StructureToPtr"); - protected static readonly MethodInfo marshal_ptrtostructure = typeof (Marshal).GetMethod ("PtrToStructure", BindingFlags.Static | BindingFlags.Public, null, new Type [] { typeof (IntPtr), typeof (Type) }, null); - protected static readonly MethodInfo marshal_writeintptr = typeof (Marshal).GetMethod ("WriteIntPtr", BindingFlags.Static | BindingFlags.Public, null, new Type [] { typeof (IntPtr), typeof (IntPtr) }, null); - protected static readonly FieldInfo intptr_zero = typeof (IntPtr).GetField ("Zero"); - - // These methods might be more commonly overridden for a given C++ ABI: - - public virtual MethodType GetMethodType (CppTypeInfo typeInfo, MethodInfo imethod) - { - if (IsInline (imethod) && !IsVirtual (imethod) && typeInfo.Library.InlineMethodPolicy == InlineMethods.NotPresent) - return MethodType.NotImplemented; - else if (imethod.IsDefined (typeof (ConstructorAttribute), false)) - return MethodType.NativeCtor; - else if (imethod.Name.Equals ("Alloc")) - return MethodType.ManagedAlloc; - else if (imethod.IsDefined (typeof (DestructorAttribute), false)) - return MethodType.NativeDtor; - - return MethodType.Native; - } - - // Implementing this is recommended.. - // otherwise it is not possible to instantiate classes that have vtables and only implicitly defined ctor - // Return null if not implemented or if the symbol name of the vtable for the passed typeInfo cannot be mangled (i.e. because there's no vtable) - protected virtual string GetMangledVTableName (CppTypeInfo typeInfo) - { - return null; - } - - // The members below must be implemented for a given C++ ABI: - - public abstract CallingConvention? GetCallingConvention (MethodInfo methodInfo); - protected abstract string GetMangledMethodName (CppTypeInfo typeInfo, MethodInfo methodInfo); - - // --------------------------------- - - private struct EmptyNativeLayout { } - - public virtual ICppClass ImplementClass (CppTypeInfo typeInfo) - { - if (typeInfo.WrapperType == null || !wrapper_to_typeinfo.ContainsKey (typeInfo.WrapperType)) { - - if (typeInfo.WrapperType != null) - wrapper_to_typeinfo.Add (typeInfo.WrapperType, typeInfo); - - DefineImplType (typeInfo); - - var properties = GetProperties (typeInfo.InterfaceType); - var methods = GetMethods (typeInfo.InterfaceType).Select (m => GetPInvokeSignature (typeInfo, m)); - - // Implement all methods - int vtableIndex = 0; - foreach (var method in methods) - DefineMethod (typeInfo, method, ref vtableIndex); - - // Implement all properties - foreach (var property in properties) - DefineProperty (typeInfo, property); - - typeInfo.emit_info.ctor_il.Emit (OpCodes.Ret); - - var native_vtable = default (IntPtr); - -#if INIT_NATIVE_VTABLES - var vtable_symbol = GetMangledVTableName (typeInfo); - if (vtable_symbol != null) - native_vtable = SymbolResolver.ResolveSymbol (SymbolResolver.LoadImage (ref typeInfo.Library.name), vtable_symbol); -#endif - return (ICppClass)Activator.CreateInstance (typeInfo.emit_info.type_builder.CreateType (), typeInfo, native_vtable); - } - - throw new InvalidOperationException ("This type has already been implemented"); - } - - public virtual CppTypeInfo MakeTypeInfo (CppLibrary lib, string typeName, Type interfaceType, Type layoutType/*?*/, Type/*?*/ wrapperType) - { - Debug.Assert (lib.Abi == this); - return new CppTypeInfo (lib, typeName, interfaceType, layoutType ?? typeof (EmptyNativeLayout), wrapperType); - } - - public virtual IEnumerable GetVirtualMethodSlots (CppTypeInfo typeInfo, Type interfaceType) - { - return from m in GetMethods (interfaceType) - where IsVirtual (m) - select GetPInvokeSignature (typeInfo, m); - } - - protected virtual IEnumerable GetMethods (Type interfaceType) - { - // get all methods defined on inherited interfaces first - var methods = ( - from iface in interfaceType.GetInterfaces () - from method in iface.GetMethods () - where !method.IsSpecialName - select method - ).Concat ( - from method in interfaceType.GetMethods () - where !method.IsSpecialName - orderby method.MetadataToken - select method - ); - - return methods; - } - - protected virtual IEnumerable GetProperties (Type interfaceType) - { - return ( // get all properties defined on the interface - from property in interfaceType.GetProperties () - select property - ).Union ( // ... as well as those defined on inherited interfaces - from iface in interfaceType.GetInterfaces () - from property in iface.GetProperties () - select property - ); - } - - protected virtual void DefineImplType (CppTypeInfo typeInfo) - { - string implTypeName = typeInfo.InterfaceType.Name + "_"; - if (typeInfo.NativeLayout != null) - implTypeName += typeInfo.NativeLayout.Name + "_"; - implTypeName += this.GetType ().Name + "_Impl"; - - var impl_type = CppLibrary.interopModule.DefineType (implTypeName, TypeAttributes.Class | TypeAttributes.Sealed); - impl_type.AddInterfaceImplementation (typeInfo.InterfaceType); - - var typeinfo_field = impl_type.DefineField ("_typeInfo", typeof (CppTypeInfo), FieldAttributes.InitOnly | FieldAttributes.Private); - var native_vtable_field = impl_type.DefineField ("_nativeVTable", typeof (IntPtr), FieldAttributes.InitOnly | FieldAttributes.Private); - - ConstructorBuilder ctor = impl_type.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard, - new Type[] { typeof (CppTypeInfo), typeof (IntPtr) }); - - var ctor_il = ctor.GetILGenerator (); - - // this._typeInfo = (CppTypeInfo passed to constructor) - ctor_il.Emit (OpCodes.Ldarg_0); - ctor_il.Emit (OpCodes.Ldarg_1); - ctor_il.Emit (OpCodes.Stfld, typeinfo_field); - - // this._nativeVTable = (vtable ptr passed to constructor) - ctor_il.Emit (OpCodes.Ldarg_0); - ctor_il.Emit (OpCodes.Ldarg_2); - ctor_il.Emit (OpCodes.Stfld, native_vtable_field); - - typeInfo.emit_info.ctor_il = ctor_il; - typeInfo.emit_info.typeinfo_field = typeinfo_field; - typeInfo.emit_info.native_vtable_field = native_vtable_field; - typeInfo.emit_info.type_builder = impl_type; - } - - protected virtual MethodBuilder DefineMethod (CppTypeInfo typeInfo, PInvokeSignature psig, ref int vtableIndex) - { - var interfaceMethod = psig.OrigMethod; - - // 1. Generate managed trampoline to call native method - var trampoline = GetMethodBuilder (typeInfo, interfaceMethod); - var il = typeInfo.emit_info.current_il = trampoline.GetILGenerator (); - - switch (psig.Type) { - - case MethodType.NotImplemented: - il.Emit (OpCodes.Ldstr, "This method is not available."); - il.Emit (OpCodes.Newobj, notimplementedexception); - il.Emit (OpCodes.Throw); - - goto case MethodType.NoOp; // fallthrough - case MethodType.NoOp: - // return NULL if method is supposed to return a value - if (!interfaceMethod.ReturnType.Equals (typeof (void))) - il.Emit (OpCodes.Ldnull); - il.Emit (OpCodes.Ret); - return trampoline; - - case MethodType.ManagedAlloc: - EmitManagedAlloc (typeInfo, interfaceMethod); - il.Emit (OpCodes.Ret); - return trampoline; - } - - var isStatic = IsStatic (interfaceMethod); - LocalBuilder cppInstancePtr = null; - LocalBuilder nativePtr = null; - - // If we're an instance method, load up the "this" pointer - if (!isStatic) - { - if (psig.ParameterTypes.Count == 0) - throw new ArgumentException ("First argument to non-static C++ method must be instance pointer."); - - // 2. Load the native C++ instance pointer - EmitLoadInstancePtr (il, interfaceMethod.GetParameters () [0].ParameterType, out cppInstancePtr, out nativePtr); - - // 3. Make sure our native pointer is a valid reference. If not, throw ObjectDisposedException - EmitCheckDisposed (il, nativePtr, psig.Type); - } - - MethodInfo nativeMethod; - - if (IsVirtual (interfaceMethod) && psig.Type != MethodType.NativeDtor) { - nativeMethod = EmitPrepareVirtualCall (typeInfo, cppInstancePtr, vtableIndex++); - } else { - if (IsVirtual (interfaceMethod)) - vtableIndex++; - - nativeMethod = GetPInvokeForMethod (typeInfo, psig); - } - - switch (psig.Type) { - case MethodType.NativeCtor: - EmitConstruct (typeInfo, nativeMethod, psig, cppInstancePtr, nativePtr); - break; - case MethodType.NativeDtor: - EmitDestruct (typeInfo, nativeMethod, psig, cppInstancePtr, nativePtr); - break; - default: - EmitNativeCall (typeInfo, nativeMethod, psig, nativePtr); - break; - } - - il.Emit (OpCodes.Ret); - return trampoline; - } - - protected virtual PropertyBuilder DefineProperty (CppTypeInfo typeInfo, PropertyInfo property) - { - if (property.CanWrite) - throw new InvalidProgramException ("Properties in C++ interface must be read-only."); - - var imethod = property.GetGetMethod (); - var methodName = imethod.Name; - var propName = property.Name; - var retType = imethod.ReturnType; - - var fieldProp = typeInfo.emit_info.type_builder.DefineProperty (propName, PropertyAttributes.None, retType, Type.EmptyTypes); - - var methodAttr = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.HideBySig; - var fieldGetter = typeInfo.emit_info.type_builder.DefineMethod (methodName, methodAttr, retType, Type.EmptyTypes); - var il = fieldGetter.GetILGenerator (); - - // C++ interface properties are either to return the CppTypeInfo or to access C++ fields - if (retType.IsGenericType && retType.GetGenericTypeDefinition ().Equals (typeof (CppField<>))) { - - // define a new field for the property - var fieldData = typeInfo.emit_info.type_builder.DefineField ("__" + propName + "_Data", retType, FieldAttributes.InitOnly | FieldAttributes.Private); - - // we need to lazy init the field because we don't have accurate field offset until after - // all base classes have been added (by ctor) - var lazyInit = il.DefineLabel (); - - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ldfld, fieldData); - il.Emit (OpCodes.Dup); - il.Emit (OpCodes.Brfalse_S, lazyInit); - il.Emit (OpCodes.Ret); - - // init new CppField - il.MarkLabel (lazyInit); - il.Emit (OpCodes.Pop); - - il.Emit (OpCodes.Ldarg_0); - - // first, get field offset - // = ((int)Marshal.OffsetOf (layout_type, propName)) + FieldOffsetPadding; - il.Emit(OpCodes.Ldtoken, typeInfo.NativeLayout); - il.Emit(OpCodes.Call, type_gettypefromhandle); - il.Emit(OpCodes.Ldstr, propName); - il.Emit(OpCodes.Call, marshal_offsetof); - - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ldfld, typeInfo.emit_info.typeinfo_field); - il.Emit (OpCodes.Callvirt, typeinfo_fieldoffset); - - il.Emit (OpCodes.Add); - - // new CppField () - il.Emit (OpCodes.Newobj, retType.GetConstructor (new Type[] { typeof(int) })); - - il.Emit (OpCodes.Stfld, fieldData); - - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ldfld, fieldData); - il.Emit (OpCodes.Ret); - - } else if (retType.Equals (typeof (CppTypeInfo))) { - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ldfld, typeInfo.emit_info.typeinfo_field); - il.Emit (OpCodes.Ret); - } else - throw new InvalidProgramException ("Properties in C++ interface can only be of type CppField."); - - fieldProp.SetGetMethod (fieldGetter); - - return fieldProp; - } - - /** - * Implements the managed trampoline that will be invoked from the vtable by native C++ code when overriding - * the specified C++ virtual method with the specified managed one. - */ - // FIXME: This should be moved into CppTypeInfo class - internal virtual Delegate GetManagedOverrideTrampoline (CppTypeInfo typeInfo, int vtableIndex) - { - if (typeInfo.WrapperType == null) - return null; - - var sig = typeInfo.VirtualMethods [vtableIndex]; - if (sig == null) - return null; - - var interfaceMethod = sig.OrigMethod; - var targetMethod = FindManagedOverrideTarget (typeInfo.WrapperType, interfaceMethod); - if (targetMethod == null) - return null; - - var interfaceArgs = ReflectionHelper.GetMethodParameterTypes (interfaceMethod); - var nativeArgs = sig.ParameterTypes.ToArray (); - - // TODO: According to http://msdn.microsoft.com/en-us/library/w16z8yc4.aspx - // The dynamic method created with this constructor has access to public and internal members of all the types contained in module m. - // This does not appear to hold true, so we also disable JIT visibility checks. - var trampolineIn = new DynamicMethod (typeInfo.WrapperType.Name + "_" + interfaceMethod.Name + "_FromNative", sig.ReturnType, - nativeArgs, typeof (CppInstancePtr).Module, true); - - ReflectionHelper.ApplyMethodParameterAttributes (interfaceMethod, trampolineIn, true); - var il = trampolineIn.GetILGenerator (); - - // for static (target) methods: - OpCode callInstruction = OpCodes.Call; - int argLoadStart = IsStatic (interfaceMethod)? 0 : 1; // chop off C++ instance ptr if there is one - - // for instance methods, we need a managed instance to call them on! - if (!targetMethod.IsStatic) { - callInstruction = OpCodes.Callvirt; - argLoadStart = 1; - - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ldc_I4, typeInfo.GCHandleOffset); - - var getManagedObj = cppip_tomanaged_size.MakeGenericMethod (typeInfo.WrapperType); - il.Emit (OpCodes.Call, getManagedObj); - } - - for (int i = argLoadStart; i < interfaceArgs.Length; i++) { - il.Emit (OpCodes.Ldarg, i); - EmitInboundMarshal (il, nativeArgs [i], interfaceArgs [i]); - } - - il.Emit (callInstruction, targetMethod); - EmitOutboundMarshal (il, targetMethod.ReturnType, sig.ReturnType); - il.Emit (OpCodes.Ret); - - return trampolineIn.CreateDelegate (typeInfo.VTableDelegateTypes [vtableIndex]); - } - - protected virtual MethodInfo FindManagedOverrideTarget (Type wrapper, MethodInfo interfaceMethod) - { - if (interfaceMethod == null) - return null; - - var possibleMembers = wrapper.FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.NonPublic | - BindingFlags.Instance | BindingFlags.Static, vtable_override_filter, interfaceMethod); - - if (possibleMembers.Length > 1) - throw new InvalidProgramException ("More than one possible override found when binding virtual method: " + interfaceMethod.Name); - else if (possibleMembers.Length == 0) - return null; - - return (MethodInfo)possibleMembers [0]; - } - - /** - * Defines a new MethodBuilder with the same signature as the passed MethodInfo - */ - protected virtual MethodBuilder GetMethodBuilder (CppTypeInfo typeInfo, MethodInfo interfaceMethod) - { - var parameterTypes = ReflectionHelper.GetMethodParameterTypes (interfaceMethod); - var methodBuilder = typeInfo.emit_info.type_builder.DefineMethod (interfaceMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, - interfaceMethod.ReturnType, parameterTypes); - ReflectionHelper.ApplyMethodParameterAttributes (interfaceMethod, methodBuilder, false); - return methodBuilder; - } - - /** - * Defines a new MethodBuilder that calls the specified C++ (non-virtual) method using its mangled name - */ - protected virtual MethodBuilder GetPInvokeForMethod (CppTypeInfo typeInfo, PInvokeSignature sig) - { - var entryPoint = sig.Name; - if (entryPoint == null) - throw new NotSupportedException ("Could not mangle method name."); - - string lib; - if (IsInline (sig.OrigMethod) && typeInfo.Library.InlineMethodPolicy == InlineMethods.SurrogateLib) - lib = typeInfo.Library.Name + "-inline"; - else - lib = typeInfo.Library.Name; - - var builder = typeInfo.emit_info.type_builder.DefinePInvokeMethod (entryPoint, lib, entryPoint, - MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.PinvokeImpl, - CallingConventions.Standard, sig.ReturnType, sig.ParameterTypes.ToArray (), - sig.CallingConvention.Value, CharSet.Ansi); - builder.SetImplementationFlags (builder.GetMethodImplementationFlags () | MethodImplAttributes.PreserveSig); - ReflectionHelper.ApplyMethodParameterAttributes (sig.OrigMethod, builder, true); - return builder; - } - - /** - * Emits the IL to load the correct delegate instance and/or retrieve the MethodInfo from the VTable - * for a C++ virtual call. - */ - protected virtual MethodInfo EmitPrepareVirtualCall (CppTypeInfo typeInfo, LocalBuilder cppInstancePtr, int vtableIndex) - { - var il = typeInfo.emit_info.current_il; - var vtableDelegateType = typeInfo.VTableDelegateTypes [vtableIndex]; - var getDelegate = typeinfo_adjvcall.MakeGenericMethod (vtableDelegateType); - - // this._typeInfo.GetAdjustedVirtualCall (cppInstancePtr, vtableIndex); - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ldfld, typeInfo.emit_info.typeinfo_field); - il.Emit (OpCodes.Ldloc_S, cppInstancePtr); - il.Emit (OpCodes.Ldc_I4, vtableIndex); - il.Emit (OpCodes.Callvirt, getDelegate); - - return ReflectionHelper.GetMethodInfoForDelegate (vtableDelegateType); - } - - /** - * Emits IL to allocate the memory for a new instance of the C++ class. - * To complete method, emit OpCodes.Ret. - */ - protected virtual void EmitManagedAlloc (CppTypeInfo typeInfo, MethodInfo interfaceMethod) - { - var il = typeInfo.emit_info.current_il; - var cppip = il.DeclareLocal (typeof (CppInstancePtr)); - - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ldfld, typeInfo.emit_info.typeinfo_field); - - if (typeInfo.WrapperType != null && interfaceMethod.GetParameters ().Any ()) { - // load managed wrapper - il.Emit (OpCodes.Ldarg_1); - il.Emit (OpCodes.Newobj, cppip_fromtype_managed); - } else { - il.Emit (OpCodes.Callvirt, typeinfo_nativesize); - il.Emit (OpCodes.Newobj, cppip_fromsize); - } - il.Emit (OpCodes.Stloc, cppip); - - var unknown_native_vtable = il.DefineLabel (); - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ldfld, typeInfo.emit_info.native_vtable_field); - il.Emit (OpCodes.Brfalse_S, unknown_native_vtable); - - il.Emit (OpCodes.Ldloca, cppip); - il.Emit (OpCodes.Call, cppip_native); - - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ldfld, typeInfo.emit_info.native_vtable_field); - il.Emit (OpCodes.Call, marshal_writeintptr); - - il.MarkLabel (unknown_native_vtable); - il.Emit (OpCodes.Ldloc, cppip); - } - - protected virtual void EmitConstruct (CppTypeInfo typeInfo, MethodInfo nativeMethod, PInvokeSignature psig, - LocalBuilder cppInstancePtr, LocalBuilder nativePtr) - { - Debug.Assert (psig.Type == MethodType.NativeCtor); - var il = typeInfo.emit_info.current_il; - - EmitNativeCall (typeInfo, nativeMethod, psig, nativePtr); - - if (cppInstancePtr != null && psig.OrigMethod.ReturnType == typeof (CppInstancePtr)) { - EmitInitVTable (typeInfo, cppInstancePtr); - il.Emit (OpCodes.Ldloc_S, cppInstancePtr); - - } else if (psig.OrigMethod.DeclaringType.GetInterfaces ().Any (i => i.IsGenericType && i.GetGenericTypeDefinition () == typeof (ICppClassOverridable<>))) { - throw new InvalidProgramException ("In ICppClassOverridable, native constructors must take as first argument and return CppInstancePtr"); - } - } - - protected virtual void EmitDestruct (CppTypeInfo typeInfo, MethodInfo nativeMethod, PInvokeSignature psig, - LocalBuilder cppInstancePtr, LocalBuilder nativePtr) - { - Debug.Assert (psig.Type == MethodType.NativeDtor); - var il = typeInfo.emit_info.current_il; - - // we don't do anything if the object wasn't managed alloc - if (cppInstancePtr == null) - return; - - EmitCheckManagedAlloc (il, cppInstancePtr); - - EmitResetVTable (typeInfo, cppInstancePtr); - EmitNativeCall (typeInfo, nativeMethod, psig, nativePtr); - } - - /** - * Emits IL to call the native method. nativeMethod should be either a method obtained by - * GetPInvokeForMethod or the MethodInfo of a vtable method. - * To complete method, emit OpCodes.Ret. - */ - protected virtual void EmitNativeCall (CppTypeInfo typeInfo, MethodInfo nativeMethod, PInvokeSignature psig, LocalBuilder nativePtr) - { - var il = typeInfo.emit_info.current_il; - var interfaceMethod = psig.OrigMethod; - var interfaceArgs = interfaceMethod.GetParameters (); - - int argLoadStart = 1; // For static methods, just strip off arg0 (.net this pointer) - if (!IsStatic (interfaceMethod)) - { - argLoadStart = 2; // For instance methods, strip off CppInstancePtr and pass the corresponding IntPtr - il.Emit (OpCodes.Ldloc_S, nativePtr); - } - - // load and marshal arguments - for (int i = argLoadStart; i <= interfaceArgs.Length; i++) { - il.Emit (OpCodes.Ldarg, i); - EmitOutboundMarshal (il, interfaceArgs [i - 1].ParameterType, psig.ParameterTypes [i - 1]); - } - - il.Emit (OpCodes.Call, nativeMethod); - - // Marshal return value - if (psig.Type != MethodType.NativeCtor) - EmitInboundMarshal (il, psig.ReturnType, interfaceMethod.ReturnType); - } - - - public virtual PInvokeSignature GetPInvokeSignature (CppTypeInfo typeInfo, MethodInfo method) - { - var methodType = GetMethodType (typeInfo, method); - var parameters = method.GetParameters (); - var pinvokeTypes = new List (parameters.Length); - - foreach (var pi in parameters) { - pinvokeTypes.Add (ToPInvokeType (pi.ParameterType, pi)); - } - - return new PInvokeSignature { - OrigMethod = method, - Name = GetMangledMethodName (typeInfo, method), - Type = methodType, - CallingConvention = GetCallingConvention (method), - ParameterTypes = pinvokeTypes, - ReturnType = methodType == MethodType.NativeCtor? typeof (void) : - ToPInvokeType (method.ReturnType, method.ReturnTypeCustomAttributes) - }; - } - - public virtual Type ToPInvokeType (Type t, ICustomAttributeProvider icap) - { - if (t == typeof (bool)) { - return typeof (byte); - - } else if (typeof (ICppObject).IsAssignableFrom (t)) { - - if (IsByVal (icap)) { - - return GetTypeInfo (t).NativeLayout; - - } else { // by ref - - return typeof (IntPtr); - } - } - - return t; - } - - // The above should return parameter/return types that - // correspond with the marshalling implemented in the next 2 methods. - - // This method marshals from managed -> C++ - // The value it is marshaling will be on the stack. - protected virtual void EmitOutboundMarshal (ILGenerator il, Type managedType, Type targetType) - { - var nextArg = il.DefineLabel (); - - // FIXME: Why is this needed ? - // auto marshal bool to C++ bool type (0 = false , 1 = true ) - if (managedType.Equals (typeof (bool))) { - Label isTrue = il.DefineLabel (); - Label done = il.DefineLabel (); - il.Emit (OpCodes.Brtrue, isTrue); - il.Emit (OpCodes.Ldc_I4_0); - il.Emit (OpCodes.Br, done); - il.MarkLabel (isTrue); - il.Emit (OpCodes.Ldc_I4_1); - il.MarkLabel (done); - //il.Emit (OpCodes.Conv_I1); - } - - // auto marshal ICppObject - if (typeof (ICppObject).IsAssignableFrom (managedType)) { - - var nullCase = il.DefineLabel (); - var param = il.DeclareLocal (typeof (CppInstancePtr)); - - // check for null - il.Emit (OpCodes.Dup); - il.Emit (OpCodes.Brfalse_S, nullCase); - - // FIXME: ICppObject could be implemented by a value type - il.Emit (OpCodes.Callvirt, cppobj_native); - il.Emit (OpCodes.Stloc, param); - - if (targetType == typeof (IntPtr)) { // by ref - il.Emit (OpCodes.Ldloca, param); - il.Emit (OpCodes.Call, cppip_native); - - il.Emit (OpCodes.Br_S, nextArg); - - il.MarkLabel (nullCase); - // Null case - il.Emit (OpCodes.Pop); - il.Emit (OpCodes.Ldsfld, intptr_zero); - - } else { // by val - - var val = il.DeclareLocal (targetType); - il.Emit (OpCodes.Ldloca, val); // dest - - il.Emit (OpCodes.Ldloca, param); - il.Emit (OpCodes.Call, cppip_native); // src - - il.Emit (OpCodes.Cpobj, targetType); - il.Emit (OpCodes.Ldloc, val); - - il.Emit (OpCodes.Br_S, nextArg); - - il.MarkLabel (nullCase); - // Null case - il.Emit (OpCodes.Ldstr, "Cannot pass null object of type '" + managedType + "' to c++ by value"); - il.Emit (OpCodes.Newobj, typeof (ArgumentException).GetConstructor (new Type[] { typeof(string) })); - il.Emit (OpCodes.Throw); - } - } - - il.MarkLabel (nextArg); - } - - - // This method marshals from C++ -> managed - // The value it is marshaling will be on the stack. - protected virtual void EmitInboundMarshal (ILGenerator il, Type nativeType, Type targetType) - { - if (nativeType == typeof (void)) - return; // <- yes, this is necessary - - var next = il.DefineLabel (); - var ptr = il.DeclareLocal (typeof (CppInstancePtr)); - - // marshal IntPtr -> ICppObject - if (nativeType == typeof (IntPtr) && typeof (ICppObject).IsAssignableFrom (targetType)) { - - var isNull = il.DefineLabel (); - - // first, we check for null - il.Emit (OpCodes.Dup); - il.Emit (OpCodes.Brfalse_S, isNull); - - il.Emit (OpCodes.Newobj, cppip_fromnative); - il.Emit (OpCodes.Stloc, ptr); - EmitCreateCppObjectFromNative (il, targetType, ptr); - il.Emit (OpCodes.Br_S, next); - - il.MarkLabel (isNull); - il.Emit (OpCodes.Pop); - il.Emit (OpCodes.Ldnull); - - } else if (nativeType.IsValueType && typeof (ICppObject).IsAssignableFrom (targetType)) { - // marshal value type -> ICppObject - - // Obviously, we lose all managed overrides if we pass by value, - // but this "slicing" happens in vanilla C++ as well - - il.Emit (OpCodes.Box, nativeType); // structure - - il.Emit (OpCodes.Sizeof, nativeType); - il.Emit (OpCodes.Newobj, cppip_fromsize); - il.Emit (OpCodes.Stloc, ptr); - il.Emit (OpCodes.Ldloca, ptr); - il.Emit (OpCodes.Call, cppip_native); // ptr - - il.Emit (OpCodes.Ldc_I4_0); // fDeleteOld - - il.Emit (OpCodes.Call, marshal_structuretoptr); - EmitCreateCppObjectFromNative (il, targetType, ptr); - } - - il.MarkLabel (next); - } - - // Gets a typeinfo for another ICppObject. - protected virtual CppTypeInfo GetTypeInfo (Type otherWrapperType) - { - CppTypeInfo info; - if (wrapper_to_typeinfo.TryGetValue (otherWrapperType, out info)) - return info; - - // pass a "dummy" type info to subclass ctor to trigger the creation of the real one - try { - Activator.CreateInstance (otherWrapperType, (CppTypeInfo)(new DummyCppTypeInfo ())); - - } catch (MissingMethodException) { - - throw new InvalidProgramException (string.Format ("Type `{0}' implements ICppObject but does not contain a public constructor that takes CppTypeInfo", otherWrapperType)); - } - - return wrapper_to_typeinfo [otherWrapperType]; - } - - - - // Expects cppip = CppInstancePtr local - protected virtual void EmitCreateCppObjectFromNative (ILGenerator il, Type targetType, LocalBuilder cppip) - { - CppTypeInfo targetTypeInfo = null; - if (targetType == typeof (ICppObject)) - targetType = typeof (CppInstancePtr); - - // check for a native constructor (i.e. a public ctor in the wrapper that takes CppInstancePtr) - if (typeof (ICppObject).IsAssignableFrom (targetType)) { - var ctor = targetType.GetConstructor (BindingFlags.ExactBinding | BindingFlags.Public | BindingFlags.Instance, null, new Type [] { typeof (CppInstancePtr) }, null); - if (ctor == null) - throw new InvalidProgramException (string.Format ("Type `{0}' implements ICppObject but does not contain a public constructor that takes CppInstancePtr", targetType)); - - // Basically emitting this: - // CppInstancePtr.ToManaged (native) ?? new targetType (native) - // ..but ToManaged is only called if there's a vtable (FIXME: otherwise we rewrap) - - var hasWrapper = il.DefineLabel (); - - if (targetTypeInfo == null) - targetTypeInfo = GetTypeInfo (targetType); // FIXME: woof. do we really have to do this? - if (targetTypeInfo != null && targetTypeInfo.HasVTable) { - il.Emit (OpCodes.Ldloca, cppip); - il.Emit (OpCodes.Call, cppip_native); - il.Emit (OpCodes.Call, cppip_tomanaged.MakeGenericMethod (targetType)); - il.Emit (OpCodes.Dup); - il.Emit (OpCodes.Brtrue_S, hasWrapper); - il.Emit (OpCodes.Pop); - } - - il.Emit (OpCodes.Ldloc, cppip); - il.Emit (OpCodes.Newobj, ctor); - - il.MarkLabel (hasWrapper); - - } else if (targetType.IsValueType) { - - // (targetType)Marshal.PtrToStructure (CppInstancePtr.Native, typeof (targetType)) - il.Emit (OpCodes.Ldloca, cppip); - il.Emit (OpCodes.Call, cppip_native); - il.Emit (OpCodes.Ldtoken, targetType); - il.Emit (OpCodes.Call, type_gettypefromhandle); - il.Emit (OpCodes.Call, marshal_ptrtostructure); - il.Emit (OpCodes.Unbox_Any, targetType); - } - } - - /** - * Emits IL to load the VTable object onto the stack. - */ - protected virtual void EmitLoadVTable (CppTypeInfo typeInfo) - { - var il = typeInfo.emit_info.current_il; - - // this._typeInfo.VTable - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ldfld, typeInfo.emit_info.typeinfo_field); - il.Emit (OpCodes.Callvirt, typeinfo_vtable); - } - - /** - * Emits IL to set the vtable pointer of the instance (if class has a vtable). - * This should usually happen in the managed wrapper of the C++ instance constructor. - */ - protected virtual void EmitInitVTable (CppTypeInfo typeInfo, LocalBuilder cppip) - { - var il = typeInfo.emit_info.current_il; - - // this._typeInfo.VTable.InitInstance (cppInstancePtr); - EmitLoadVTable (typeInfo); - il.Emit (OpCodes.Ldloca_S, cppip); - EmitCallVTableMethod (typeInfo, vtable_initinstance, 2, false); - } - - protected virtual void EmitResetVTable (CppTypeInfo typeInfo, LocalBuilder cppip) - { - var il = typeInfo.emit_info.current_il; - - // this._typeInfo.VTable.ResetInstance (cppInstancePtr); - EmitLoadVTable (typeInfo); - il.Emit (OpCodes.Ldloc_S, cppip); - EmitCallVTableMethod (typeInfo, vtable_resetinstance, 2, false); - } - - /** - * A utility function to emit the IL for a vtable-dependant operation. - * In other words, classes with no virtual methods will not have vtables, - * so this method emits code to check for that and either throw an exception - * or do nothing if no vtable exists. To use, push the arguments to the method you - * want to call and pass the stackHeight for the call. If no vtable exists, this method - * will emit code to pop the arguments off the stack. - */ - protected virtual void EmitCallVTableMethod (CppTypeInfo typeInfo, MethodInfo method, int stackHeight, bool throwOnNoVTable) - { - var il = typeInfo.emit_info.current_il; - - // prepare a jump; do not call vtable method if no vtable - var noVirt = il.DefineLabel (); - var dontPushOrThrow = il.DefineLabel (); - - EmitLoadVTable (typeInfo); - il.Emit (OpCodes.Brfalse_S, noVirt); // if (vtableInfo == null) goto noVirt - - il.Emit (OpCodes.Callvirt, method); // call method - il.Emit (OpCodes.Br_S, dontPushOrThrow); // goto dontPushOrThrow - - il.MarkLabel (noVirt); - // noVirt: - // since there is no vtable, we did not make the method call. - // pop arguments - for (int i = 0; i < stackHeight; i++) - il.Emit (OpCodes.Pop); - - // if the method was supposed to return a value, we must - // still push something onto the stack - // FIXME: This is a kludge. What about value types? - if (!method.ReturnType.Equals (typeof (void))) - il.Emit (OpCodes.Ldnull); - - if (throwOnNoVTable) { - il.Emit (OpCodes.Ldstr, "Native class has no VTable."); - il.Emit (OpCodes.Newobj, typeof (InvalidOperationException).GetConstructor(new Type[] {typeof (string)})); - il.Emit (OpCodes.Throw); - } - - il.MarkLabel (dontPushOrThrow); - } - - protected virtual void EmitLoadInstancePtr (ILGenerator il, Type firstParamType, out LocalBuilder cppip, - out LocalBuilder native) - { - cppip = null; - native = null; - - il.Emit (OpCodes.Ldarg_1); - if (firstParamType.Equals (typeof (CppInstancePtr))) { - cppip = il.DeclareLocal (typeof (CppInstancePtr)); - native = il.DeclareLocal (typeof (IntPtr)); - il.Emit (OpCodes.Stloc_S, cppip); - il.Emit (OpCodes.Ldloca_S, cppip); - il.Emit (OpCodes.Call, cppip_native); - il.Emit (OpCodes.Stloc_S, native); - } else if (firstParamType.Equals (typeof (IntPtr))) { - native = il.DeclareLocal (typeof (IntPtr)); - il.Emit (OpCodes.Stloc_S, native); - } else if (firstParamType.IsByRef) { - native = il.DeclareLocal (firstParamType); - il.Emit (OpCodes.Stloc_S, native); - } else - throw new ArgumentException ("First argument to non-static C++ method must be byref, IntPtr or CppInstancePtr."); - } - - protected virtual void EmitCheckManagedAlloc (ILGenerator il, LocalBuilder cppip) - { - // make sure we were allocated by managed code - // if not, return - var managedAlloc = il.DefineLabel (); - - il.Emit (OpCodes.Ldloca_S, cppip); - il.Emit (OpCodes.Call, cppip_managedalloc); - il.Emit (OpCodes.Brtrue_S, managedAlloc); - il.Emit (OpCodes.Ret); - il.MarkLabel (managedAlloc); - } - - /** - * throw ObjectDisposedException if we have a null pointer for native - * however, allow destructor to be called even if we're disposed (just return immediately) - */ - protected virtual void EmitCheckDisposed (ILGenerator il, LocalBuilder native, MethodType methodType) - { - var validRef = il.DefineLabel (); - - il.Emit (OpCodes.Ldloc_S, native); - il.Emit (OpCodes.Brtrue_S, validRef); - - if (methodType == MethodType.NativeDtor) { - il.Emit (OpCodes.Ret); - il.MarkLabel (validRef); - } else { - il.Emit (OpCodes.Ldstr, String.Empty); - il.Emit (OpCodes.Newobj, typeof (ObjectDisposedException).GetConstructor (new Type[] { typeof(string) })); - il.Emit (OpCodes.Throw); - il.MarkLabel (validRef); - } - } - } - -} diff --git a/src/Mono.Cxxi/Abi/EmitInfo.cs b/src/Mono.Cxxi/Abi/EmitInfo.cs deleted file mode 100644 index 6b12ce48..00000000 --- a/src/Mono.Cxxi/Abi/EmitInfo.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Reflection.Emit; - -namespace Mono.Cxxi.Abi { - - public class EmitInfo { - public TypeBuilder type_builder; - public FieldBuilder typeinfo_field, native_vtable_field; - public ILGenerator ctor_il, current_il; - } -} - diff --git a/src/Mono.Cxxi/Abi/Impl/ItaniumAbi.cs b/src/Mono.Cxxi/Abi/Impl/ItaniumAbi.cs deleted file mode 100644 index 4b078413..00000000 --- a/src/Mono.Cxxi/Abi/Impl/ItaniumAbi.cs +++ /dev/null @@ -1,335 +0,0 @@ -// -// Mono.Cxxi.Abi.ItaniumAbi.cs: An implementation of the Itanium C++ ABI -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// Copyright 2011 Xamarin Inc (http://www.xamarin.com) -// -// 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. - -using System; -using System.Linq; -using System.Text; -using System.Reflection; -using System.Reflection.Emit; -using System.Collections.Generic; -using System.Runtime.InteropServices; - -using Mono.Cxxi.Util; - -namespace Mono.Cxxi.Abi { - public class ItaniumAbi : CppAbi { - - public static readonly ItaniumAbi Instance = new ItaniumAbi (); - - private ItaniumAbi () - { - } - - public override CppTypeInfo MakeTypeInfo (CppLibrary lib, string typeName, Type interfaceType, Type layoutType/*?*/, Type/*?*/ wrapperType) - { - return new ItaniumTypeInfo (lib, typeName, interfaceType, layoutType, wrapperType); - } - - public override IEnumerable GetVirtualMethodSlots (CppTypeInfo typeInfo, Type interfaceType) - { - foreach (var method in base.GetVirtualMethodSlots (typeInfo, interfaceType)) { - if (!IsVirtual (method.OrigMethod)) - continue; - - yield return method; - - // Itanium has extra slot for virt dtor - if (method.Type == MethodType.NativeDtor) - yield return null; - } - } - - internal override Delegate GetManagedOverrideTrampoline (CppTypeInfo typeInfo, int vtableIndex) - { - - // FIXME: HACK! we really need to support by val return types for managed override trampolines - if (typeInfo.VirtualMethods [vtableIndex] != null && - IsByVal (typeInfo.VirtualMethods [vtableIndex].OrigMethod.ReturnTypeCustomAttributes)) - return null; - - return base.GetManagedOverrideTrampoline (typeInfo, vtableIndex); - } - - protected override MethodBuilder DefineMethod (CppTypeInfo typeInfo, PInvokeSignature sig, ref int vtableIndex) - { - var builder = base.DefineMethod (typeInfo, sig, ref vtableIndex); - - // increment vtableIndex an extra time for that extra vdtor slot (already incremented once in base) - if (IsVirtual (sig.OrigMethod) && sig.Type == MethodType.NativeDtor) - vtableIndex++; - - return builder; - } - - public override CallingConvention? GetCallingConvention (MethodInfo methodInfo) - { - return CallingConvention.Cdecl; - } - - protected override string GetMangledMethodName (CppTypeInfo typeInfo, MethodInfo methodInfo) - { - var compressMap = new Dictionary (); - var methodName = methodInfo.Name; - var type = typeInfo.GetMangleType (); - var className = type.ElementTypeName; - - MethodType methodType = GetMethodType (typeInfo, methodInfo); - ParameterInfo [] parameters = methodInfo.GetParameters (); - - StringBuilder nm = new StringBuilder ("_ZN", 30); - - if (IsConst (methodInfo)) - nm.Append ('K'); - - if (type.Namespaces != null) { - foreach (var ns in type.Namespaces) - nm.Append (GetIdentifier (compressMap, ns)); - } - - nm.Append (GetIdentifier (compressMap, className)); - - // FIXME: Implement compression completely - - switch (methodType) { - case MethodType.NativeCtor: - nm.Append ("C1"); - break; - - case MethodType.NativeDtor: - nm.Append ("D1"); - break; - - default: - nm.Append (methodName.Length).Append (methodName); - break; - } - - nm.Append ('E'); - int argStart = (IsStatic (methodInfo)? 0 : 1); - - if (parameters.Length == argStart) // no args (other than C++ "this" object) - nm.Append ('v'); - else - for (int i = argStart; i < parameters.Length; i++) - nm.Append (GetTypeCode (GetMangleType (parameters [i], parameters [i].ParameterType), compressMap)); - - return nm.ToString (); - } - - public virtual string GetTypeCode (CppType mangleType) { - return GetTypeCode (mangleType, new Dictionary ()); - } - - string GetTypeCode (CppType mangleType, Dictionary compressMap) - { - CppTypes element = mangleType.ElementType; - IEnumerable modifiers = mangleType.Modifiers; - - StringBuilder code = new StringBuilder (); - - var ptrOrRef = For.AnyInputIn (CppModifiers.Pointer, CppModifiers.Reference); - var modifierCode = modifiers.Reverse ().Transform ( - For.AnyInputIn (CppModifiers.Pointer, CppModifiers.Array).Emit ("P"), - For.AnyInputIn (CppModifiers.Reference).Emit ("R"), - - // Itanium mangled names do not include const or volatile unless - // they modify the type pointed to by pointer or reference. - Choose.TopOne ( - For.AllInputsIn (CppModifiers.Volatile, CppModifiers.Const).InAnyOrder ().After (ptrOrRef).Emit ("VK"), - For.AnyInputIn (CppModifiers.Volatile).After (ptrOrRef).Emit ("V"), - For.AnyInputIn (CppModifiers.Const).After (ptrOrRef).Emit ("K") - ) - ); - code.Append (string.Join(string.Empty, modifierCode.ToArray ())); - - switch (element) { - case CppTypes.Int: - code.Append (modifiers.Transform ( - For.AllInputsIn (CppModifiers.Unsigned, CppModifiers.Short).InAnyOrder ().Emit ('t'), - For.AnyInputIn (CppModifiers.Short).Emit ('s'), - For.AllInputsIn (CppModifiers.Unsigned, CppModifiers.Long, CppModifiers.Long).InAnyOrder ().Emit ('y'), - For.AllInputsIn (CppModifiers.Long, CppModifiers.Long).InAnyOrder ().Emit ('x'), - For.AllInputsIn (CppModifiers.Unsigned, CppModifiers.Long).InAnyOrder ().Emit ('m'), - For.AnyInputIn (CppModifiers.Long).Emit ('l'), - For.AnyInputIn (CppModifiers.Unsigned).Emit ('j') - ).DefaultIfEmpty ('i').ToArray ()); - break; - case CppTypes.Bool: - code.Append ('b'); - break; - case CppTypes.Char: - if (modifiers.Contains (CppModifiers.Signed)) - code.Append ('a'); - else if (modifiers.Contains (CppModifiers.Unsigned)) - code.Append ('h'); - else - code.Append ('c'); - break; - case CppTypes.Float: - code.Append ('f'); - break; - case CppTypes.Double: - if (modifiers.Contains (CppModifiers.Long)) - code.Append ('e'); - else - code.Append ('d'); - break; - case CppTypes.Class: - case CppTypes.Struct: - case CppTypes.Union: - case CppTypes.Enum: - if (mangleType.Namespaces != null) { - code.Append ('N'); - foreach (var ns in mangleType.Namespaces) - code.Append (GetIdentifier (compressMap, ns)); - } - - code.Append (GetIdentifier (compressMap, mangleType.ElementTypeName)); - - if (mangleType.Namespaces != null) - code.Append ('E'); - break; - - } - - return code.ToString (); - } - - protected override string GetMangledVTableName (CppTypeInfo typeInfo) - { - var compressMap = new Dictionary (); - var type = typeInfo.GetMangleType (); - var nm = new StringBuilder ("_ZTV", 30); - - if (type.Namespaces != null) { - nm.Append ('N'); - foreach (var ns in type.Namespaces) - nm.Append (GetIdentifier (compressMap, ns)); - } - - nm.Append (GetIdentifier (compressMap, type.ElementTypeName)); - - if (type.Namespaces != null) - nm.Append ('E'); - - return nm.ToString (); - } - - string GetIdentifier (Dictionary compressMap, string identifier) - { - int cid; - if (compressMap.TryGetValue (identifier, out cid)) - return cid == 0 ? "S_" : ToBase36String (cid - 1); - compressMap [identifier] = compressMap.Count; - return identifier.Length.ToString () + identifier; - } - - const string Base36 = "0123456789abcdefghijklmnopqrstuvwxyz"; - string ToBase36String (int input) - { - var result = new Stack (); - while (input != 0) - { - result.Push (Base36 [input % 36]); - input /= 36; - } - return new string (result.ToArray ()); - } - - // Section 3.1.4: - // Classes with non-default copy ctors/destructors are returned using a hidden - // argument - bool ReturnByHiddenArgument (CppTypeInfo typeInfo, MethodInfo method) - { - var iti = (ItaniumTypeInfo)typeInfo; - - if (!IsByVal (method.ReturnTypeCustomAttributes)) - return false; - - if (iti.has_non_default_copy_ctor_or_dtor == null) - iti.has_non_default_copy_ctor_or_dtor = GetMethods (typeInfo.InterfaceType) - .Any (m => (IsCopyConstructor (m) || - GetMethodType (typeInfo, m) == MethodType.NativeDtor) && - !IsArtificial (m)); - - return iti.has_non_default_copy_ctor_or_dtor.Value; - } - - public override PInvokeSignature GetPInvokeSignature (CppTypeInfo/*?*/ typeInfo, MethodInfo method) - { - var psig = base.GetPInvokeSignature (typeInfo, method); - - if (ReturnByHiddenArgument (typeInfo, method)) { - psig.ParameterTypes.Insert (0, typeof (IntPtr)); - psig.ReturnType = typeof (void); - } - - return psig; - } - - protected override void EmitNativeCall (CppTypeInfo typeInfo, MethodInfo nativeMethod, PInvokeSignature psig, LocalBuilder nativePtr) - { - var il = typeInfo.emit_info.current_il; - var method = psig.OrigMethod; - var returnType = method.ReturnType; - var hiddenReturnByValue = ReturnByHiddenArgument (typeInfo, method); - - LocalBuilder returnValue = null; - - if (hiddenReturnByValue) - { - returnValue = il.DeclareLocal (typeof (CppInstancePtr)); - - if (typeof (ICppObject).IsAssignableFrom (returnType)) - il.Emit (OpCodes.Ldc_I4, GetTypeInfo (returnType).NativeSize); - else if (returnType.IsValueType) - il.Emit (OpCodes.Ldc_I4, Marshal.SizeOf (returnType)); - - il.Emit (OpCodes.Newobj, cppip_fromsize); - il.Emit (OpCodes.Stloc, returnValue); - il.Emit (OpCodes.Ldloca, returnValue); - il.Emit (OpCodes.Call, cppip_native); - } - - base.EmitNativeCall (typeInfo, nativeMethod, psig, nativePtr); - - if (hiddenReturnByValue) { - EmitCreateCppObjectFromNative (il, returnType, returnValue); - - if (returnType.IsValueType) { - // FIXME: This dispose should prolly be in a Finally block.. - il.Emit (OpCodes.Ldloca, returnValue); - il.Emit (OpCodes.Call, cppip_dispose); - } - } - } - - - } -} \ No newline at end of file diff --git a/src/Mono.Cxxi/Abi/Impl/ItaniumTypeInfo.cs b/src/Mono.Cxxi/Abi/Impl/ItaniumTypeInfo.cs deleted file mode 100644 index aaa5dcfd..00000000 --- a/src/Mono.Cxxi/Abi/Impl/ItaniumTypeInfo.cs +++ /dev/null @@ -1,87 +0,0 @@ -// -// Mono.Cxxi.Abi.ItaniumTypeInfo.cs: An implementation of the Itanium C++ ABI -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// -// Copyright (C) 2011 Alexander Corrado -// -// 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. - -using System; -using System.Linq; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Reflection; - -using Mono.Cxxi.Util; - -namespace Mono.Cxxi.Abi { - - public class ItaniumTypeInfo : CppTypeInfo { - - protected internal bool? has_non_default_copy_ctor_or_dtor; - - public ItaniumTypeInfo (CppLibrary lib, string typeName, Type interfaceType, Type nativeLayout, Type/*?*/ wrapperType) - : base (lib, typeName, interfaceType, nativeLayout, wrapperType) - { - } -/* - protected override void AddBase (CppTypeInfo baseType, BaseVirtualMethods location) - { - if (TypeComplete) - return; - - // When adding a non-primary base class's complete vtable, we need to reserve space for - // the stuff before the address point of the vtptr.. - // Includes vbase & vcall offsets (virtual inheritance), offset to top, and RTTI info - if (addVTable) { - - // FIXME: virtual inheritance - virtual_methods.Add (null); - virtual_methods.Add (null); - - vt_overrides.Add (2); - vt_delegate_types.Add (2); - } - - base.AddBase (baseType, addVTable); - } -*/ - protected override bool OnVTableDuplicate (ref int iter, ref int adj, PInvokeSignature sig, PInvokeSignature dup) - { - var isOverride = base.OnVTableDuplicate (ref iter, ref adj, sig, dup); - if (isOverride && sig.Type == MethodType.NativeDtor) { - - // also remove that pesky extra dtor - virtual_methods.RemoveAt (iter + 1); - vt_overrides.Remove (1); - vt_delegate_types.Remove (1); - vtable_index_adjustments.Add (0); - adj--; - return true; - } - - return false; - } - - } -} - diff --git a/src/Mono.Cxxi/Abi/Impl/MsvcAbi.cs b/src/Mono.Cxxi/Abi/Impl/MsvcAbi.cs deleted file mode 100644 index 49bdc307..00000000 --- a/src/Mono.Cxxi/Abi/Impl/MsvcAbi.cs +++ /dev/null @@ -1,220 +0,0 @@ -// -// Mono.Cxxi.Abi.MsvcAbi.cs: An implementation of the Microsoft Visual C++ ABI -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// -// 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. - -using System; -using System.Linq; -using System.Text; -using System.Reflection; -using System.Collections.Generic; -using System.Runtime.InteropServices; - -using Mono.Cxxi; -using Mono.Cxxi.Util; - -namespace Mono.Cxxi.Abi { - - // FIXME: No 64-bit support - public class MsvcAbi : CppAbi { - - public static readonly MsvcAbi Instance = new MsvcAbi (); - - private MsvcAbi () - { - } - - public override CallingConvention? GetCallingConvention (MethodInfo methodInfo) - { - // FIXME: Varargs methods ... ? - - if (IsStatic (methodInfo)) - return CallingConvention.Cdecl; - else - return CallingConvention.ThisCall; - } - - protected override string GetMangledMethodName (CppTypeInfo typeInfo, MethodInfo methodInfo) - { - var methodName = methodInfo.Name; - var type = typeInfo.GetMangleType (); - var className = type.ElementTypeName; - - MethodType methodType = GetMethodType (typeInfo, methodInfo); - ParameterInfo [] parameters = methodInfo.GetParameters (); - - StringBuilder nm = new StringBuilder ("?", 30); - - if (methodType == MethodType.NativeCtor) - nm.Append ("?0"); - else if (methodType == MethodType.NativeDtor) - nm.Append ("?1"); - else - nm.Append (methodName).Append ('@'); - - // FIXME: This has to include not only the name of the immediate containing class, - // but also all names of containing classes and namespaces up the hierarchy. - nm.Append (className).Append ("@@"); - - // function modifiers are a matrix of consecutive uppercase letters - // depending on access type and virtual (far)/static (far)/far modifiers - - // first, access type - char funcModifier = 'Q'; // (public) - if (IsProtected (methodInfo)) - funcModifier = 'I'; - else if (IsPrivate (methodInfo)) // (probably don't need this) - funcModifier = 'A'; - - // now, offset based on other modifiers - if (IsStatic (methodInfo)) - funcModifier += (char)2; - else if (IsVirtual (methodInfo)) - funcModifier += (char)4; - - nm.Append (funcModifier); - - // FIXME: deal with other storage classes for "this" i.e. the "volatile" in -> int foo () volatile; - if (!IsStatic (methodInfo)) { - if (IsConst (methodInfo)) - nm.Append ('B'); - else - nm.Append ('A'); - } - - switch (GetCallingConvention (methodInfo)) { - case CallingConvention.Cdecl: - nm.Append ('A'); - break; - case CallingConvention.ThisCall: - nm.Append ('E'); - break; - case CallingConvention.StdCall: - nm.Append ('G'); - break; - case CallingConvention.FastCall: - nm.Append ('I'); - break; - } - - // FIXME: handle const, volatile modifiers on return type - // FIXME: the manual says this is only omitted for simple types.. are we doing the right thing here? - CppType returnType = GetMangleType (methodInfo.ReturnTypeCustomAttributes, methodInfo.ReturnType); - if (returnType.ElementType == CppTypes.Class || - returnType.ElementType == CppTypes.Struct || - returnType.ElementType == CppTypes.Union) - nm.Append ("?A"); - - if (methodType == MethodType.NativeCtor || methodType == MethodType.NativeDtor) - nm.Append ('@'); - else - nm.Append (GetTypeCode (returnType)); - - int argStart = (IsStatic (methodInfo)? 0 : 1); - if (parameters.Length == argStart) { // no args (other than C++ "this" object) - nm.Append ("XZ"); - return nm.ToString (); - } else - for (int i = argStart; i < parameters.Length; i++) - nm.Append (GetTypeCode (GetMangleType (parameters [i], parameters [i].ParameterType))); - - nm.Append ("@Z"); - return nm.ToString (); - } - - public virtual string GetTypeCode (CppType mangleType) - { - CppTypes element = mangleType.ElementType; - IEnumerable modifiers = mangleType.Modifiers; - - StringBuilder code = new StringBuilder (); - - var ptr = For.AnyInputIn (CppModifiers.Pointer); - var ptrRefOrArray = For.AnyInputIn (CppModifiers.Pointer, CppModifiers.Reference, CppModifiers.Array); - - var modifierCode = modifiers.Reverse ().Transform ( - - Choose.TopOne ( - For.AllInputsIn (CppModifiers.Const, CppModifiers.Volatile).InAnyOrder ().After (ptrRefOrArray).Emit ('D'), - For.AnyInputIn (CppModifiers.Const).After (ptrRefOrArray).Emit ('B'), - For.AnyInputIn (CppModifiers.Volatile).After (ptrRefOrArray).Emit ('C'), - For.AnyInput ().After (ptrRefOrArray).Emit ('A') - ), - - For.AnyInputIn (CppModifiers.Array).Emit ('Q'), - For.AnyInputIn (CppModifiers.Reference).Emit ('A'), - - Choose.TopOne ( - ptr.After ().AllInputsIn (CppModifiers.Const, CppModifiers.Volatile).InAnyOrder ().Emit ('S'), - ptr.After ().AnyInputIn (CppModifiers.Const).Emit ('Q'), - ptr.After ().AnyInputIn (CppModifiers.Volatile).Emit ('R'), - ptr.Emit ('P') - ), - - ptrRefOrArray.AtEnd ().Emit ('A') - ); - code.Append (modifierCode.ToArray ()); - - switch (element) { - case CppTypes.Void: - code.Append ('X'); - break; - case CppTypes.Int: - code.Append (modifiers.Transform ( - For.AllInputsIn (CppModifiers.Unsigned, CppModifiers.Short).InAnyOrder ().Emit ('G') - ).DefaultIfEmpty ('H').ToArray ()); - break; - case CppTypes.Char: - code.Append ('D'); - break; - case CppTypes.Class: - code.Append ('V'); - code.Append(mangleType.ElementTypeName); - code.Append ("@@"); - break; - case CppTypes.Struct: - code.Append ('U'); - code.Append(mangleType.ElementTypeName); - code.Append ("@@"); - break; - case CppTypes.Union: - code.Append ('T'); - code.Append(mangleType.ElementTypeName); - code.Append ("@@"); - break; - case CppTypes.Enum: - code.Append ("W4"); - code.Append(mangleType.ElementTypeName); - code.Append ("@@"); - break; - } - - return code.ToString (); - } - - } -} - diff --git a/src/Mono.Cxxi/Abi/MethodType.cs b/src/Mono.Cxxi/Abi/MethodType.cs deleted file mode 100644 index dc393b85..00000000 --- a/src/Mono.Cxxi/Abi/MethodType.cs +++ /dev/null @@ -1,39 +0,0 @@ -// -// Mono.Cxxi.Abi.MethodType.cs: Method annotation for IL codegen -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// -// 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. - -using System; -namespace Mono.Cxxi.Abi { - public enum MethodType { - NoOp, - NotImplemented, - Native, - NativeCtor, - NativeDtor, - ManagedAlloc - } -} diff --git a/src/Mono.Cxxi/Abi/SymbolResolver.cs b/src/Mono.Cxxi/Abi/SymbolResolver.cs deleted file mode 100644 index 66880104..00000000 --- a/src/Mono.Cxxi/Abi/SymbolResolver.cs +++ /dev/null @@ -1,113 +0,0 @@ -// -// Mono.Cxxi.Abi.SymbolResolver.cs: Platform-independent dynamic symbol lookup -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// -// Copyright 2011 Xamarin Inc (http://www.xamarin.com) -// -// 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. - - -using System; -using System.Runtime.InteropServices; - -namespace Mono.Cxxi.Abi { - internal static class SymbolResolver { - - static readonly string [] formats; - static readonly Func load_image; - static readonly Func resolve_symbol; - - static SymbolResolver () - { - switch (Environment.OSVersion.Platform) { - - case PlatformID.Unix: - case PlatformID.MacOSX: - load_image = dlopen; - resolve_symbol = dlsym; - formats = new[] { - "{0}", - "{0}.so", - "{0}.dylib", - "lib{0}.so", - "lib{0}.dylib", - "{0}.bundle" - }; - break; - - default: - load_image = LoadLibrary; - resolve_symbol = GetProcAddress; - formats = new[] { "{0}", "{0}.dll" }; - break; - } - } - - // will fix up name with a more precise name to speed up later p/invokes (hopefully?) - public static IntPtr LoadImage (ref string name) - { - foreach (var format in formats) { - var attempted = string.Format (format, name); - var ptr = load_image (attempted); - if (ptr != IntPtr.Zero) { - name = attempted; - return ptr; - } - } - return IntPtr.Zero; - } - - public static IntPtr ResolveSymbol (IntPtr image, string symbol) - { - if (image != IntPtr.Zero) - return resolve_symbol (image, symbol); - return IntPtr.Zero; - } - - #region POSIX - - static IntPtr dlopen (string path) - { - return dlopen (path, 0x0); - } - - [DllImport ("dl", CharSet=CharSet.Ansi)] - static extern IntPtr dlopen (string path, int flags); - - [DllImport ("dl", CharSet=CharSet.Ansi)] - static extern IntPtr dlsym (IntPtr handle, string symbol); - - #endregion - - #region Win32 - - [DllImport("kernel32", SetLastError=true)] - static extern IntPtr LoadLibrary (string lpFileName); - - [DllImport("kernel32", CharSet=CharSet.Ansi, ExactSpelling=true, SetLastError=true)] - static extern IntPtr GetProcAddress (IntPtr hModule, string procName); - - #endregion - - } -} - diff --git a/src/Mono.Cxxi/Abi/VTable.cs b/src/Mono.Cxxi/Abi/VTable.cs deleted file mode 100644 index 2d17a5c9..00000000 --- a/src/Mono.Cxxi/Abi/VTable.cs +++ /dev/null @@ -1,207 +0,0 @@ -// -// Mono.Cxxi.Abi.VTable.cs: Managed VTable Implementation -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// -// 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. - -using System; -using System.Diagnostics; -using System.Collections.Generic; - -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.InteropServices; - -namespace Mono.Cxxi.Abi { - - // TODO: RTTI .. support virtual inheritance - - public class VTable : IDisposable { - - protected bool initialized; - protected CppTypeInfo type_info; - protected IntPtr vtPtr; - - public virtual int EntryCount { - get { return type_info.VirtualMethods.Count; } - } - public virtual int EntrySize { - get { return IntPtr.Size; } - } - - // Subclasses should allocate vtPtr and then call WriteOverrides - public VTable (CppTypeInfo typeInfo) - { - this.initialized = false; - this.type_info = typeInfo; - this.vtPtr = Marshal.AllocHGlobal ((EntryCount * EntrySize) + typeInfo.VTableTopPadding + typeInfo.VTableBottomPadding); - - WriteOverrides (); - CppInstancePtr.RegisterManagedVTable (this); - } - - protected virtual void WriteOverrides () - { - IntPtr vtEntryPtr; - int currentOffset = type_info.VTableTopPadding; - for (int i = 0; i < EntryCount; i++) { - Delegate currentOverride = type_info.VTableOverrides [i]; - - if (currentOverride != null) // managed override - vtEntryPtr = Marshal.GetFunctionPointerForDelegate (currentOverride); - else - vtEntryPtr = IntPtr.Zero; - - Marshal.WriteIntPtr (vtPtr, currentOffset, vtEntryPtr); - currentOffset += EntrySize; - } - } - - public virtual T GetVirtualCallDelegate (CppInstancePtr instance, int index) - where T : class /*Delegate*/ - { - var vtable = instance.NativeVTable; - - var ftnptr = Marshal.ReadIntPtr (vtable, (index * EntrySize) + type_info.VTableTopPadding); - if (ftnptr == IntPtr.Zero) - throw new NullReferenceException ("Native VTable contains null...possible abstract class???"); - - var del = Marshal.GetDelegateForFunctionPointer (ftnptr, typeof (T)); - return del as T; - } - - // FIXME: Make this method unsafe.. it would probably be much faster - public virtual void InitInstance (ref CppInstancePtr instance) - { - var basePtr = Marshal.ReadIntPtr (instance.Native); - Debug.Assert (basePtr != IntPtr.Zero); - - if (basePtr == vtPtr) - return; - - instance.NativeVTable = basePtr; - - if (!initialized) { - - // FIXME: This could probably be a more efficient memcpy - for (int i = 0; i < type_info.VTableTopPadding; i++) - Marshal.WriteByte(vtPtr, i, Marshal.ReadByte(basePtr, i)); - - int currentOffset = type_info.VTableTopPadding; - for (int i = 0; i < EntryCount; i++) { - if (Marshal.ReadIntPtr (vtPtr, currentOffset) == IntPtr.Zero) - Marshal.WriteIntPtr (vtPtr, currentOffset, Marshal.ReadIntPtr (basePtr, currentOffset)); - - currentOffset += EntrySize; - } - - // FIXME: This could probably be a more efficient memcpy - for (int i = 0; i < type_info.VTableBottomPadding; i++) - Marshal.WriteByte(vtPtr, currentOffset + i, Marshal.ReadByte(basePtr, currentOffset + i)); - - initialized = true; - } - - Marshal.WriteIntPtr (instance.Native, vtPtr); - } - - public virtual void ResetInstance (CppInstancePtr instance) - { - Marshal.WriteIntPtr (instance.Native, instance.NativeVTable); - } - - public CppTypeInfo TypeInfo { - get { return type_info; } - } - - public IntPtr Pointer { - get { return vtPtr; } - } - - protected virtual void Dispose (bool disposing) - { - if (vtPtr != IntPtr.Zero) { - Marshal.FreeHGlobal (vtPtr); - vtPtr = IntPtr.Zero; - } - } - - // TODO: This WON'T usually be called because VTables are associated with classes - // (not instances) and managed C++ class wrappers are staticly held? - public void Dispose () - { - Dispose (true); - GC.SuppressFinalize (this); - } - - ~VTable () - { - Dispose (false); - } - - public static bool BindToSignatureAndAttribute (MemberInfo member, object obj) - { - var overrideNative = member.GetCustomAttributes (typeof (OverrideNativeAttribute), true); - if (overrideNative.Length == 0) - return false; - - var name = ((OverrideNativeAttribute)overrideNative [0]).NativeMethod ?? member.Name; - - return BindToSignature (member, obj, name); - } - - public static bool BindToSignature (MemberInfo member, object obj) - { - return BindToSignature (member, obj, member.Name); - } - - public static bool BindToSignature (MemberInfo member, object obj, string nativeMethod) - { - MethodInfo imethod = (MethodInfo) obj; - MethodInfo candidate = (MethodInfo) member; - - if (nativeMethod != imethod.Name) - return false; - - ParameterInfo[] invokeParams = imethod.GetParameters (); - ParameterInfo[] methodParams = candidate.GetParameters (); - - if (invokeParams.Length == methodParams.Length) { - for (int i = 0; i < invokeParams.Length; i++) { - if (!invokeParams [i].ParameterType.IsAssignableFrom (methodParams [i].ParameterType)) - return false; - } - } else if (invokeParams.Length == methodParams.Length + 1) { - for (int i = 1; i < invokeParams.Length; i++) { - if (!invokeParams [i].ParameterType.IsAssignableFrom (methodParams [i - 1].ParameterType)) - return false; - } - } else - return false; - - return true; - } - } -} diff --git a/src/Mono.Cxxi/AssemblyInfo.cs b/src/Mono.Cxxi/AssemblyInfo.cs deleted file mode 100644 index 22fe6da6..00000000 --- a/src/Mono.Cxxi/AssemblyInfo.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// -// 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. - -using System; -using System.Reflection; -using System.Runtime.CompilerServices; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. - -[assembly: AssemblyTitle("Mono.Cxxi")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("1.0.*")] - -// The following attributes are used to specify the signing key for the assembly, -// if desired. See the Mono documentation for more information about signing. - -//[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] - -[assembly: CLSCompliant(true)] -// FIXME: This will not work if we ever support saving these assemblies -[assembly: InternalsVisibleTo("__CppLibraryImplAssembly")] diff --git a/src/Mono.Cxxi/Attributes.cs b/src/Mono.Cxxi/Attributes.cs deleted file mode 100644 index 090ba0d8..00000000 --- a/src/Mono.Cxxi/Attributes.cs +++ /dev/null @@ -1,173 +0,0 @@ -// -// Mono.Cxxi.Attributes.cs -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// -// Copyright (C) 2010 Alexander Corrado -// - -using System; -using System.Linq; -using System.Reflection; - -namespace Mono.Cxxi { - - #region Interface method attributes - - [AttributeUsage (AttributeTargets.Method)] - public class ConstructorAttribute : Attribute {} - - [AttributeUsage (AttributeTargets.Method)] - public class DestructorAttribute : Attribute {} - - - [AttributeUsage (AttributeTargets.Method)] - public class VirtualAttribute : Attribute {} - - [AttributeUsage (AttributeTargets.Method)] - public class StaticAttribute : Attribute {} - - // used for the const "this" - for example: int value () const; - // use MangleAsAttribute for const parameters - [AttributeUsage (AttributeTargets.Method)] - public class ConstAttribute : Attribute {} - - // FIXME: Will we ever be calling private methods? - [AttributeUsage (AttributeTargets.Method)] - public class PrivateAttribute : Attribute {} - - [AttributeUsage (AttributeTargets.Method)] - public class ProtectedAttribute : Attribute {} - - [AttributeUsage (AttributeTargets.Method)] - public class InlineAttribute : Attribute {} - - [AttributeUsage (AttributeTargets.Method)] - public class ArtificialAttribute : Attribute {} - - [AttributeUsage (AttributeTargets.Method)] - public class CopyConstructorAttribute : Attribute {} - - // applied when the target would normally be passed by reference (e.g. class) - [AttributeUsage (AttributeTargets.Parameter | AttributeTargets.ReturnValue)] - public class ByValAttribute : Attribute {} - - // used for byref return of things that would normally be passed by value (e.g. int&) - [AttributeUsage (AttributeTargets.ReturnValue)] - public class ByRefAttribute : Attribute {} - - [AttributeUsage (AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.ReturnValue)] - public class MangleAsAttribute : Attribute { - public CppType MangleType { get; private set; } - - public MangleAsAttribute (CppType mangleType) - { - this.MangleType = mangleType; - } - public MangleAsAttribute (string mangleTypeStr) - { - this.MangleType = new CppType (mangleTypeStr); - } - public MangleAsAttribute (params object [] cppTypeSpec) - { - this.MangleType = new CppType (cppTypeSpec); - } - } - - // for testing: - [AttributeUsage (AttributeTargets.Method)] - public class AbiTestAttribute : Attribute { - public string MangledName { get; set; } - public Type Abi { get; set; } - - public AbiTestAttribute (string mangledName) - { - MangledName = mangledName; - } - } - - #endregion - - #region Wrapper method attributes - [AttributeUsage (AttributeTargets.Method)] - public class OverrideNativeAttribute : Attribute { - public string NativeMethod { get; set; } - public OverrideNativeAttribute () - { - } - public OverrideNativeAttribute (string nativeMethod) - { - this.NativeMethod = nativeMethod; - } - } - #endregion -} - -namespace Mono.Cxxi.Abi { -using Mono.Cxxi; - - public partial class CppAbi { - - public virtual bool IsVirtual (MethodInfo method) - { - return method.IsDefined (typeof (VirtualAttribute), false); - } - public virtual bool IsStatic (MethodInfo method) - { - return method.IsDefined (typeof (StaticAttribute), false); - } - public virtual bool IsConst (MethodInfo method) - { - return method.IsDefined (typeof (ConstAttribute), false); - } - public virtual bool IsPrivate (MethodInfo method) - { - return method.IsDefined (typeof (PrivateAttribute), false); - } - public virtual bool IsProtected (MethodInfo method) - { - return method.IsDefined (typeof (ProtectedAttribute), false); - } - public virtual bool IsInline (MethodInfo method) - { - return method.IsDefined (typeof (InlineAttribute), false); - } - public virtual bool IsArtificial (MethodInfo method) - { - return method.IsDefined (typeof (ArtificialAttribute), false); - } - public virtual bool IsCopyConstructor (MethodInfo method) - { - return method.IsDefined (typeof (CopyConstructorAttribute), false); - } - public virtual bool IsByVal (ICustomAttributeProvider icap) - { - return icap.IsDefined (typeof (ByValAttribute), false); - } - public virtual bool IsByRef (ICustomAttributeProvider icap, Type type) - { - return type.IsByRef || icap.IsDefined (typeof (ByRefAttribute), false); - } - - public virtual CppType GetMangleType (ICustomAttributeProvider icap, Type managedType) - { - CppType mangleType = new CppType (); - MangleAsAttribute maa = (MangleAsAttribute)icap.GetCustomAttributes (typeof (MangleAsAttribute), false).FirstOrDefault (); - if (maa != null) - mangleType = maa.MangleType; - - // this means that either no MangleAsAttribute was defined, or - // only CppModifiers were applied .. apply CppType from managed parameter type - if (mangleType.ElementType == CppTypes.Unknown && mangleType.ElementTypeName == null) - mangleType.CopyTypeFrom (CppType.ForManagedType (managedType)); - else if (mangleType.ElementType == CppTypes.Unknown) - // FIXME: otherwise, we just assume it's CppTypes.Class for now. - mangleType.ElementType = CppTypes.Class; - - return mangleType; - } - - } - -} diff --git a/src/Mono.Cxxi/CppField.cs b/src/Mono.Cxxi/CppField.cs deleted file mode 100644 index 3902da69..00000000 --- a/src/Mono.Cxxi/CppField.cs +++ /dev/null @@ -1,113 +0,0 @@ -// -// Mono.Cxxi.CppField.cs: Represents a field in a native C++ object -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// Copyright 2011 Xamarin Inc (http://www.xamarin.com) -// -// 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. - -using System; -using System.Runtime.InteropServices; - -namespace Mono.Cxxi { - public class CppField { - private int fieldOffset; - - public CppField (int fieldOffset) - { - this.fieldOffset = fieldOffset; - } - - public T this [CppInstancePtr ip] { - get { - - Type retType = typeof (T).IsEnum? Enum.GetUnderlyingType (typeof (T)) : typeof (T); - object retVal; - - if (retType.Equals (typeof (IntPtr))) - retVal = Marshal.ReadIntPtr (ip.Native, fieldOffset); - else if (retType.Equals (typeof (Byte))) - retVal = Marshal.ReadByte (ip.Native, fieldOffset); - else if (retType.Equals (typeof (Int16))) - retVal = Marshal.ReadInt16 (ip.Native, fieldOffset); - else if (retType.Equals (typeof (Int32))) - retVal = Marshal.ReadInt32 (ip.Native, fieldOffset); - - else if (typeof (ICppObject).IsAssignableFrom (retType)) { - - var ptr = Marshal.ReadIntPtr (ip.Native, fieldOffset); - if (ptr == IntPtr.Zero) - return default (T); - - var ctor = retType.GetConstructor (new Type [] { typeof (IntPtr) }); - if (ctor != null) { - - retVal = ctor.Invoke (new object [] { ptr }); - - } else { - ctor = retType.GetConstructor (new Type [] { typeof (CppInstancePtr) }); - if (ctor == null) - throw new NotSupportedException ("Type " + retType.Name + " does not have a constructor that takes either IntPtr or CppInstancePtr."); - - retVal = ctor.Invoke (new object [] { new CppInstancePtr (ptr) }); - } - - } else { - throw new NotSupportedException ("Cannot read C++ fields of type " + retType.Name); - } - - return (T)retVal; - } - set { - Type setType = typeof (T).IsEnum? Enum.GetUnderlyingType (typeof (T)) : typeof (T); - object setVal = value; - - if (setType.Equals (typeof (IntPtr))) - Marshal.WriteIntPtr (ip.Native, fieldOffset, (IntPtr)setVal); - else if (setType.Equals (typeof (Byte))) - Marshal.WriteByte (ip.Native, fieldOffset, (byte)setVal); - else if (setType.Equals (typeof (Int16))) - Marshal.WriteInt16 (ip.Native, fieldOffset, (Int16)setVal); - else if (setType.Equals (typeof (Int32))) - Marshal.WriteInt32 (ip.Native, fieldOffset, (Int32)setVal); - - else if (typeof (ICppObject).IsAssignableFrom (setType)) { - - if (value == null) { - Marshal.WriteIntPtr (ip.Native, fieldOffset, IntPtr.Zero); - - } else { - - var cppobj = (ICppObject)value; - Marshal.WriteIntPtr (ip.Native, fieldOffset, (IntPtr)cppobj.Native); - } - - } else { - throw new NotSupportedException ("Cannot write C++ fields of type " + setType.Name); - } - - } - } - } -} diff --git a/src/Mono.Cxxi/CppInstancePtr.cs b/src/Mono.Cxxi/CppInstancePtr.cs deleted file mode 100644 index 91a9b6c0..00000000 --- a/src/Mono.Cxxi/CppInstancePtr.cs +++ /dev/null @@ -1,201 +0,0 @@ -// -// Mono.Cxxi.CppInstancePtr.cs: Represents a pointer to a native C++ instance -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// -// 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. - -using System; -using System.Reflection.Emit; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Diagnostics; - -using Mono.Cxxi.Abi; - -namespace Mono.Cxxi { - public struct CppInstancePtr : ICppObject { - - private IntPtr ptr, native_vtptr; - private bool manage_memory; - - private static Dictionary managed_vtptr_to_gchandle_offset = null; - - // Alloc a new C++ instance - internal CppInstancePtr (CppTypeInfo typeInfo, object managedWrapper) - { - // Under the hood, we're secretly subclassing this C++ class to store a - // handle to the managed wrapper. - int allocSize = typeInfo.GCHandleOffset + IntPtr.Size; - ptr = Marshal.AllocHGlobal (allocSize); - - // NOTE: native_vtptr will be set later after native ctor is called - native_vtptr = IntPtr.Zero; - - // zero memory for sanity - // FIXME: This should be an initblk - byte[] zeroArray = new byte [allocSize]; - Marshal.Copy (zeroArray, 0, ptr, allocSize); - - IntPtr handlePtr = MakeGCHandle (managedWrapper); - Marshal.WriteIntPtr (ptr, typeInfo.GCHandleOffset, handlePtr); - - manage_memory = true; - } - - // Alloc a new C++ instance when there is no managed wrapper. - internal CppInstancePtr (int nativeSize) - { - ptr = Marshal.AllocHGlobal (nativeSize); - native_vtptr = IntPtr.Zero; - manage_memory = true; - } - - // Gets a casted CppInstancePtr - internal CppInstancePtr (CppInstancePtr instance, int offset) - { - // FIXME: On NET_4_0 use IntPtr.Add - ptr = new IntPtr (instance.Native.ToInt64 () + offset); - native_vtptr = IntPtr.Zero; - manage_memory = false; - } - - // Get a CppInstancePtr for an existing C++ instance from an IntPtr - public CppInstancePtr (IntPtr native) - { - if (native == IntPtr.Zero) - throw new ArgumentOutOfRangeException ("native cannot be null pointer"); - - ptr = native; - native_vtptr = IntPtr.Zero; - manage_memory = false; - } - - // Fulfills ICppObject requirement - public CppInstancePtr (CppInstancePtr copy) - { - this.ptr = copy.ptr; - this.native_vtptr = copy.native_vtptr; - this.manage_memory = copy.manage_memory; - } - - // Provide casts to/from IntPtr: - public static implicit operator CppInstancePtr (IntPtr native) - { - return new CppInstancePtr (native); - } - - // cast from CppInstancePtr -> IntPtr is explicit because we lose information - public static explicit operator IntPtr (CppInstancePtr ip) - { - return ip.Native; - } - - public IntPtr Native { - get { - if (ptr == IntPtr.Zero) - throw new ObjectDisposedException ("CppInstancePtr"); - - return ptr; - } - } - - // Internal for now to prevent attempts to read vtptr from non-virtual class - internal IntPtr NativeVTable { - get { - - if (native_vtptr == IntPtr.Zero) { - // For pointers from native code... - // Kludge! CppInstancePtr doesn't know whether this class is virtual or not, but we'll just assume that either - // way it's at least sizeof(void*) and read what would be the vtptr anyway. Supposedly, if it's not virtual, - // the wrappers won't use this field anyway... - native_vtptr = Marshal.ReadIntPtr (ptr); - } - - return native_vtptr; - } - set { - native_vtptr = value; - } - } - - CppInstancePtr ICppObject.Native { - get { return this; } - } - - public bool IsManagedAlloc { - get { return manage_memory; } - } - - internal static void RegisterManagedVTable (VTable vtable) - { - if (managed_vtptr_to_gchandle_offset == null) - managed_vtptr_to_gchandle_offset = new Dictionary (); - - managed_vtptr_to_gchandle_offset [vtable.Pointer] = vtable.TypeInfo.GCHandleOffset; - } - - internal static IntPtr MakeGCHandle (object managedWrapper) - { - // TODO: Dispose() should probably be called at some point on this GCHandle. - GCHandle handle = GCHandle.Alloc (managedWrapper, GCHandleType.Normal); - return GCHandle.ToIntPtr (handle); - } - - // This might be made public, but in this form it only works for classes with vtables. - // Returns null if the native ptr passed in does not appear to be a managed instance. - // (i.e. its vtable ptr is not in managed_vtptr_to_gchandle_offset) - internal static T ToManaged (IntPtr native) where T : class - { - if (managed_vtptr_to_gchandle_offset == null) - return null; - - int gchOffset; - if (!managed_vtptr_to_gchandle_offset.TryGetValue (Marshal.ReadIntPtr (native), out gchOffset)) - return null; - - return ToManaged (native, gchOffset); - } - - // WARNING! This method is not safe. DO NOT call - // if we do not KNOW that this instance is managed. - internal static T ToManaged (IntPtr native, int nativeSize) where T : class - { - IntPtr handlePtr = Marshal.ReadIntPtr (native, nativeSize); - GCHandle handle = GCHandle.FromIntPtr (handlePtr); - - return handle.Target as T; - } - - // TODO: Free GCHandle? - public void Dispose () - { - if (manage_memory && ptr != IntPtr.Zero) - Marshal.FreeHGlobal (ptr); - - ptr = IntPtr.Zero; - manage_memory = false; - } - } -} diff --git a/src/Mono.Cxxi/CppLibrary.cs b/src/Mono.Cxxi/CppLibrary.cs deleted file mode 100644 index 7b648101..00000000 --- a/src/Mono.Cxxi/CppLibrary.cs +++ /dev/null @@ -1,139 +0,0 @@ -// -// Mono.Cxxi.CppLibrary.cs: Represents a native C++ library for interop -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// -// 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. - - -using System; -using System.IO; -using System.Collections.Generic; -using System.Runtime.InteropServices; - -using System.Reflection; -using System.Reflection.Emit; - -using Mono.Cxxi.Abi; - -namespace Mono.Cxxi { - - public enum InlineMethods { - - // Normally, C++ inline methods are not exported from the library, so C++ interop cannot call them. - // This is the default option. It throws a NotImplementedException if you try to call the native version of one of these methods. - // Use this if you reimplement the inline methods in managed code, or if they are not to be available in the bindings. - NotPresent, - - // Expect the inline methods to be present in the specified library - // For example, if the library was compiled with GCC's -fkeep-inline-functions option - Present, - - // Expect the inline methods to be exported in a separate library named %name%-inline - SurrogateLib, - } - - public sealed class CppLibrary { - internal static AssemblyBuilder interopAssembly; - internal static ModuleBuilder interopModule; - - public CppAbi Abi { get; private set; } - public InlineMethods InlineMethodPolicy { get; private set; } - - internal string name; - public string Name { get { return name; } } - - static CppLibrary () - { - AssemblyName assemblyName = new AssemblyName ("__CppLibraryImplAssembly"); - string moduleName = "CppLibraryImplAssembly.dll"; - - interopAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.RunAndSave); - interopModule = interopAssembly.DefineDynamicModule (moduleName, moduleName, true); - } - - public CppLibrary (string name) - : this (name, InlineMethods.NotPresent) - { - } - - public CppLibrary (string name, InlineMethods inlinePolicy) - : this (name, ItaniumAbi.Instance, inlinePolicy) - { - //FIXME: Ideally we would auto-detect ABI here. - } - - public CppLibrary (string name, CppAbi abi, InlineMethods inlinePolicy) - { - if (name == null) - throw new ArgumentNullException ("Name cannot be NULL."); - if (abi == null) - throw new ArgumentNullException ("Abi cannot be NULL."); - - this.name = name; - this.Abi = abi; - this.InlineMethodPolicy = inlinePolicy; - } - - // Mainly for debugging at this point - public static void SaveInteropAssembly () - { - interopAssembly.Save ("CppLibraryImplAssembly.dll"); - } - - // For working with a class that you are not instantiating - // from managed code and where access to fields is not necessary - public Iface GetClass (string className) - where Iface : ICppClass - { - var typeInfo = Abi.MakeTypeInfo (this, className, typeof (Iface), null, null); - return (Iface)Abi.ImplementClass (typeInfo); - } - - // For instantiating or working with a class that may have fields - // but where overriding virtual methods in managed code is not necessary - public Iface GetClass (string className) - where Iface : ICppClassInstantiatable - where NativeLayout : struct - { - var typeInfo = Abi.MakeTypeInfo (this, className, typeof (Iface), typeof (NativeLayout), null); - return (Iface)Abi.ImplementClass (typeInfo); - } - - /* The most powerful override. Allows the following from managed code: - * + Instantiation - * + Field access - * + Virtual method overriding - */ - public Iface GetClass (string className) - where Iface : ICppClassOverridable - where NativeLayout : struct - where Managed : ICppObject - { - var typeInfo = Abi.MakeTypeInfo (this, className, typeof (Iface), typeof (NativeLayout), typeof (Managed)); - return (Iface)Abi.ImplementClass (typeInfo); - } - - } -} diff --git a/src/Mono.Cxxi/CppModifiers.cs b/src/Mono.Cxxi/CppModifiers.cs deleted file mode 100644 index 30cb60eb..00000000 --- a/src/Mono.Cxxi/CppModifiers.cs +++ /dev/null @@ -1,197 +0,0 @@ -// -// Mono.Cxxi.CppModifiers.cs: Abstracts a C++ type modifiers -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// -// 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. - -using System; -using System.Linq; -using System.Collections.Generic; -using System.Text.RegularExpressions; - -using Mono.Cxxi.Util; - -namespace Mono.Cxxi { - - public abstract class CppModifiers { - #pragma warning disable 0414 - static int tmp; - #pragma warning restore - // This can be added to at runtime to support other modifiers - // The list should be prioritized, in that the first items should be modifiers that can potentially contain other modifiers - public static readonly Dictionary>> Tokenize = new Dictionary>> () { - { "\\<(.*)\\>", (m,l) => l.AddFirst (m.Groups [1].Success && m.Groups [1].Value.Trim () != ""? new TemplateModifier (m.Groups [1].Value) : CppModifiers.Template) }, - { "\\[([^\\]]*)\\]", (m,l) => l.Add (m.Groups [1].Success && m.Groups [1].Value.Trim () != "" && int.TryParse (m.Groups [1].Value, out tmp) ? new ArrayModifier (int.Parse (m.Groups [1].Value)) : CppModifiers.Array) }, - { "\\bconst\\b", (m,l) => l.Add (CppModifiers.Const) }, - { "\\*", (m,l) => l.Add (CppModifiers.Pointer) }, - { "\\&", (m,l) => l.Add (CppModifiers.Reference) }, - { "\\bvolatile\\b", (m,l) => l.Add (CppModifiers.Volatile) }, - { "\\bunsigned\\b", (m,l) => l.Add (CppModifiers.Unsigned) }, - { "\\bsigned\\b", (m,l) => l.Add (CppModifiers.Signed) }, - { "\\bshort\\b", (m,l) => l.Add (CppModifiers.Short) }, - { "\\blong\\b", (m,l) => l.Add (CppModifiers.Long) } - }; - - private struct Token { - public Action> action; - public Match match; - } - private static IEnumerable Tokenizer (string input) { - - foreach (var token in Tokenize) { - Match match; - - while ((match = Regex.Match (input, token.Key)) != null && match.Success) { - yield return new Token { match = match, action = token.Value }; - input = input.Remove (match.Index, match.Length); - } - } - - } - - public static List Parse (string input) - { - List cpm = new List (); - var tokenizer = Tokenizer (input); - - foreach (var token in tokenizer.OrderBy (t => t.match.Index)) - token.action (token.match, cpm); - - return cpm; - } - - // removes any modifiers from the passed input - public static string Remove (string input) - { - foreach (var token in Tokenize) - input = Regex.Replace (input, token.Key, ""); - - return input; - } - - // normalizes the order of order-agnostic modifiers - public static IEnumerable NormalizeOrder (IEnumerable modifiers) - { - var parts = modifiers.Transform ( - For.AllInputsIn (CppModifiers.Unsigned, CppModifiers.Long).InAnyOrder ().Emit (new CppModifiers [] { CppModifiers.Unsigned, CppModifiers.Long }), - For.AllInputsIn (CppModifiers.Signed, CppModifiers.Long).InAnyOrder ().Emit (new CppModifiers [] { CppModifiers.Signed, CppModifiers.Long }), - For.AllInputsIn (CppModifiers.Unsigned, CppModifiers.Short).InAnyOrder ().Emit (new CppModifiers [] { CppModifiers.Unsigned, CppModifiers.Short }), - For.AllInputsIn (CppModifiers.Signed, CppModifiers.Short).InAnyOrder ().Emit (new CppModifiers [] { CppModifiers.Signed, CppModifiers.Short }), - - For.UnmatchedInput ().Emit (cppmod => new CppModifiers [] { cppmod }) - ); - - foreach (var array in parts) - foreach (var item in array) - yield return item; - } - - public override bool Equals (object obj) - { - return this == obj as CppModifiers; - } - public override int GetHashCode () - { - return GetType ().GetHashCode (); - } - - public static bool operator == (CppModifiers a, CppModifiers b) - { - if ((object)a == (object)b) - return true; - - if ((object)a == null || (object)b == null) - return false; - - return a.GetHashCode () == b.GetHashCode (); - } - public static bool operator != (CppModifiers a, CppModifiers b) - { - return !(a == b); - } - - public static readonly CppModifiers Const = new ConstModifier (); - public static readonly CppModifiers Pointer = new PointerModifier (); - public static readonly CppModifiers Array = new ArrayModifier (); - public static readonly CppModifiers Reference = new ReferenceModifier (); - public static readonly CppModifiers Volatile = new VolatileModifier (); - public static readonly CppModifiers Signed = new SignedModifier (); - public static readonly CppModifiers Unsigned = new UnsignedModifier (); - public static readonly CppModifiers Short = new ShortModifier (); - public static readonly CppModifiers Long = new LongModifier (); - public static readonly CppModifiers Template = new TemplateModifier (); - - // Add list of modifiers here: - public class ConstModifier : CppModifiers { public override string ToString () { return "const"; } } - public class PointerModifier : CppModifiers { public override string ToString () { return "*"; } } - public class ReferenceModifier : CppModifiers { public override string ToString () { return "&"; } } - public class VolatileModifier : CppModifiers { public override string ToString () { return "volatile"; } } - public class SignedModifier : CppModifiers { public override string ToString () { return "signed"; } } - public class UnsignedModifier : CppModifiers { public override string ToString () { return "unsigned"; } } - public class ShortModifier : CppModifiers { public override string ToString () { return "short"; } } - public class LongModifier : CppModifiers { public override string ToString () { return "long"; } } - - public class ArrayModifier : CppModifiers { - public int? Size { get; set; } - - public ArrayModifier () - { - } - - public ArrayModifier (int size) { - Size = size; - } - - public override string ToString () - { - return string.Format ("[{0}]", Size.HasValue? Size.ToString () : ""); - } - } - - public class TemplateModifier : CppModifiers { - public CppType [] Types { get; set; } - - public TemplateModifier () - { - } - - public TemplateModifier (string types) - { - Types = Regex.Split (types, "(?]*),").Select (p => new CppType (p)).ToArray (); - } - - public TemplateModifier (CppType [] types) - { - Types = types; - } - - public override string ToString () - { - return string.Format ("<{0}>", Types == null? "" : string.Join (", ", Types.Select (t => t.ToString ()).ToArray ())); - } - } - } -} - diff --git a/src/Mono.Cxxi/CppType.cs b/src/Mono.Cxxi/CppType.cs deleted file mode 100644 index b271e2ca..00000000 --- a/src/Mono.Cxxi/CppType.cs +++ /dev/null @@ -1,412 +0,0 @@ -// -// Mono.Cxxi.CppType.cs: Abstracts a C++ type declaration -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// -// 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. - -using System; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Reflection; -using System.Collections.Generic; - -using Mono.Cxxi.Util; - -namespace Mono.Cxxi { - - // These can be used anywhere a CppType could be used. - public enum CppTypes { - Unknown, - Class, - Struct, - Enum, - Union, - Void, - Bool, - Char, - Int, - Float, - Double, - WChar_T, - // for template type parameters - Typename - } - - public struct CppType { - - // FIXME: Passing these as delegates allows for the flexibility of doing processing on the - // type (i.e. to correctly mangle the function pointer arguments if the managed type is a delegate), - // however this does not make it very easy to override the default mappings at runtime. - public static List> CppTypeToManagedMap = new List> () { - (t) => (t.ElementType == CppTypes.Class || - t.ElementType == CppTypes.Struct || - (t.ElementType == CppTypes.Unknown && t.ElementTypeName != null)) && - (t.Modifiers.Count (m => m == CppModifiers.Pointer) == 1 || - t.Modifiers.Contains (CppModifiers.Reference))? typeof (ICppObject) : null, - - // void* gets IntPtr - (t) => t.ElementType == CppTypes.Void && t.Modifiers.Contains (CppModifiers.Pointer)? typeof (IntPtr) : null, - - // single pointer to char gets string - // same with wchar_t (needs marshaling attribute though!) - (t) => (t.ElementType == CppTypes.Char || t.ElementType == CppTypes.WChar_T) && t.Modifiers.Count (m => m == CppModifiers.Pointer) == 1? typeof (string) : null, - // pointer to pointer to char gets string[] - (t) => t.ElementType == CppTypes.Char && t.Modifiers.Count (m => m == CppModifiers.Pointer) == 2? typeof (string).MakeArrayType () : null, - - // arrays - (t) => t.Modifiers.Contains (CppModifiers.Array) && (t.Subtract (CppModifiers.Array).ToManagedType () != null)? t.Subtract (CppModifiers.Array).ToManagedType ().MakeArrayType () : null, - - // convert single pointers to primatives to managed byref - (t) => t.Modifiers.Count (m => m == CppModifiers.Pointer) == 1 && (t.Subtract (CppModifiers.Pointer).ToManagedType () != null)? t.Subtract (CppModifiers.Pointer).ToManagedType ().MakeByRefType () : null, - // more than one level of indirection gets IntPtr type - (t) => t.Modifiers.Contains (CppModifiers.Pointer)? typeof (IntPtr) : null, - - (t) => t.Modifiers.Contains (CppModifiers.Reference) && (t.Subtract (CppModifiers.Reference).ToManagedType () != null)? t.Subtract (CppModifiers.Reference).ToManagedType ().MakeByRefType () : null, - - (t) => t.ElementType == CppTypes.Int && t.Modifiers.Contains (CppModifiers.Short) && t.Modifiers.Contains (CppModifiers.Unsigned)? typeof (ushort) : null, - (t) => t.ElementType == CppTypes.Int && t.Modifiers.Count (m => m == CppModifiers.Long) == 2 && t.Modifiers.Contains (CppModifiers.Unsigned)? typeof (ulong) : null, - (t) => t.ElementType == CppTypes.Int && t.Modifiers.Contains (CppModifiers.Short)? typeof (short) : null, - (t) => t.ElementType == CppTypes.Int && t.Modifiers.Count (m => m == CppModifiers.Long) == 2? typeof (long) : null, - (t) => t.ElementType == CppTypes.Int && t.Modifiers.Contains (CppModifiers.Unsigned)? typeof (uint) : null, - - (t) => t.ElementType == CppTypes.Void? typeof (void) : null, - (t) => t.ElementType == CppTypes.Bool? typeof (bool) : null, - (t) => t.ElementType == CppTypes.Char? typeof (char) : null, - (t) => t.ElementType == CppTypes.Int? typeof (int) : null, - (t) => t.ElementType == CppTypes.Float? typeof (float) : null, - (t) => t.ElementType == CppTypes.Double? typeof (double) : null - }; - - public static List> ManagedToCppTypeMap = new List> () { - (t) => typeof (void).Equals (t) ? CppTypes.Void : CppTypes.Unknown, - (t) => typeof (bool).Equals (t) ? CppTypes.Bool : CppTypes.Unknown, - (t) => typeof (char).Equals (t) ? CppTypes.Char : CppTypes.Unknown, - (t) => typeof (int).Equals (t) ? CppTypes.Int : CppTypes.Unknown, - (t) => typeof (float).Equals (t) ? CppTypes.Float : CppTypes.Unknown, - (t) => typeof (double).Equals (t)? CppTypes.Double : CppTypes.Unknown, - - (t) => typeof (short).Equals (t) ? new CppType (CppModifiers.Short, CppTypes.Int) : CppTypes.Unknown, - (t) => typeof (long).Equals (t) ? new CppType (CppModifiers.Long, CppTypes.Int) : CppTypes.Unknown, - (t) => typeof (uint).Equals (t) ? new CppType (CppModifiers.Unsigned, CppTypes.Int) : CppTypes.Unknown, - (t) => typeof (ushort).Equals (t)? new CppType (CppModifiers.Unsigned, CppModifiers.Short, CppTypes.Int) : CppTypes.Unknown, - (t) => typeof (ulong).Equals (t)? new CppType (CppModifiers.Unsigned, CppModifiers.Long, CppTypes.Int) : CppTypes.Unknown, - - (t) => typeof (IntPtr).Equals (t)? new CppType (CppTypes.Void, CppModifiers.Pointer) : CppTypes.Unknown, - (t) => typeof (UIntPtr).Equals(t)? new CppType (CppTypes.Void, CppModifiers.Pointer) : CppTypes.Unknown, - - // strings mangle as "const char*" by default - (t) => typeof (string).Equals (t)? new CppType (CppModifiers.Const, CppTypes.Char, CppModifiers.Pointer) : CppTypes.Unknown, - // StringBuilder gets "char*" - (t) => typeof (StringBuilder).Equals (t)? new CppType (CppTypes.Char, CppModifiers.Pointer) : CppTypes.Unknown, - - // delegate types get special treatment - (t) => typeof (Delegate).IsAssignableFrom (t)? CppType.ForDelegate (t) : CppTypes.Unknown, - - // ... and of course ICppObjects do too! - // FIXME: We assume c++ class not struct. There should probably be an attribute - // we can apply to managed wrappers to indicate if the underlying C++ type is actually declared struct - (t) => typeof (ICppObject).IsAssignableFrom (t)? new CppType (CppTypes.Class, Regex.Replace (t.Name, "`\\d\\d?$", ""), CppModifiers.Pointer) : CppTypes.Unknown, - - // value types or interface (ICppClass) that don't fit the above categories... - (t) => t.IsValueType || t.IsInterface? new CppType (CppTypes.Class, Regex.Replace (t.Name, "`\\d\\d?$", "")) : CppTypes.Unknown, - - // convert managed type modifiers to C++ type modifiers like so: - // ref types to C++ references - // pointer types to C++ pointers - // array types to C++ arrays - (t) => { - var cppType = CppType.ForManagedType (t.GetElementType () ?? (t.IsGenericType? t.GetGenericTypeDefinition () : null)); - if (t.IsByRef) cppType.Modifiers.Add (CppModifiers.Reference); - if (t.IsPointer) cppType.Modifiers.Add (CppModifiers.Pointer); - if (t.IsArray) cppType.Modifiers.Add (CppModifiers.Array); - if (t.IsGenericType) cppType.Modifiers.Add (new CppModifiers.TemplateModifier (t.GetGenericArguments ().Select (g => CppType.ForManagedType (g)).ToArray ())); - return cppType; - } - }; - - public CppTypes ElementType { get; set; } - - // if the ElementType is Union, Struct, Class, or Enum - // this will contain the name of said type - public string ElementTypeName { get; set; } - - // may be null, and will certainly be null if ElementTypeName is null - public string [] Namespaces { get; set; } - - // this is initialized lazily to avoid unnecessary heap - // allocations if possible - private List internalModifiers; - public List Modifiers { - get { - if (internalModifiers == null) - internalModifiers = new List (); - - return internalModifiers; - } - } - - // here, you can pass in things like "const char*" or "const Foo * const" - // DISCLAIMER: this is really just for convenience for now, and is not meant to be able - // to parse even moderately complex C++ type declarations. - public CppType (string type) : this (Regex.Split (type, "\\s+(?![^\\>]*\\>|[^\\[\\]]*\\])")) - { - } - - public CppType (params object[] cppTypeSpec) : this () - { - ElementType = CppTypes.Unknown; - ElementTypeName = null; - Namespaces = null; - internalModifiers = null; - - Parse (cppTypeSpec); - } - - // FIXME: This makes no attempt to actually verify that the parts compose a valid C++ type. - private void Parse (object [] parts) - { - foreach (object part in parts) { - - if (part is CppModifiers) { - Modifiers.Add ((CppModifiers)part); - continue; - } - - if (part is CppModifiers [] || part is IEnumerable) { - Modifiers.AddRange ((IEnumerable)part); - continue; - } - - if (part is CppTypes) { - ElementType = (CppTypes)part; - continue; - } - - Type managedType = part as Type; - if (managedType != null) { - CppType mapped = CppType.ForManagedType (managedType); - CopyTypeFrom (mapped); - continue; - } - - string strPart = part as string; - if (strPart != null) { - var parsed = CppModifiers.Parse (strPart); - if (parsed.Count > 0) { - if (internalModifiers == null) - internalModifiers = parsed; - else - internalModifiers.AddRange (parsed); - - strPart = CppModifiers.Remove (strPart); - } - - // if we have something left, it must be a type name - strPart = strPart.Trim (); - if (strPart != "") { - string [] qualifiedName = strPart.Split (new string [] { "::" }, StringSplitOptions.RemoveEmptyEntries); - int numNamespaces = qualifiedName.Length - 1; - if (numNamespaces > 0) { - Namespaces = new string [numNamespaces]; - for (int i = 0; i < numNamespaces; i++) - Namespaces [i] = qualifiedName [i]; - } - strPart = qualifiedName [numNamespaces]; - - // FIXME: Fix this mess - switch (strPart) { - case "void": - ElementType = CppTypes.Void; - break; - case "bool": - ElementType = CppTypes.Bool; - break; - case "char": - ElementType = CppTypes.Char; - break; - case "int": - ElementType = CppTypes.Int; - break; - case "float": - ElementType = CppTypes.Float; - break; - case "double": - ElementType = CppTypes.Double; - break; - default: - // otherwise it is the element type name... - ElementTypeName = strPart; - break; - } - } - } - } - } - - // Applies the element type of the passed instance - // and combines its modifiers into this instance. - // Use when THIS instance may have attributes you want, - // but want the element type of the passed instance. - public CppType CopyTypeFrom (CppType type) - { - ElementType = type.ElementType; - ElementTypeName = type.ElementTypeName; - Namespaces = type.Namespaces; - - List oldModifiers = internalModifiers; - internalModifiers = type.internalModifiers; - - if (oldModifiers != null) - Modifiers.AddRange (oldModifiers); - - return this; - } - - // Removes the modifiers on the passed instance from this instance - public CppType Subtract (CppType type) - { - if (internalModifiers == null) - return this; - - CppType current = this; - foreach (var modifier in ((IEnumerable)type.Modifiers).Reverse ()) - current = current.Subtract (modifier); - - return current; - } - public CppType Subtract (CppModifiers modifier) - { - CppType newType = this; - newType.internalModifiers = new List (((IEnumerable)newType.Modifiers).Reverse ().WithoutFirst (modifier)); - return newType; - } - - // note: this adds modifiers "backwards" (it is mainly used by the generator) - public CppType Modify (CppModifiers modifier) - { - CppType newType = this; - var newModifier = new CppModifiers [] { modifier }; - - if (newType.internalModifiers != null) - newType.internalModifiers.AddFirst (newModifier); - else - newType.internalModifiers = new List (newModifier); - - return newType; - } - - public override bool Equals (object obj) - { - if (obj == null) - return false; - if (obj.GetType () == typeof (CppTypes)) - return Equals (new CppType (obj)); - if (obj.GetType () != typeof (CppType)) - return false; - CppType other = (CppType)obj; - - return (((internalModifiers == null || !internalModifiers.Any ()) && - (other.internalModifiers == null || !other.internalModifiers.Any ())) || - (internalModifiers != null && other.internalModifiers != null && - CppModifiers.NormalizeOrder (internalModifiers).SequenceEqual (CppModifiers.NormalizeOrder (other.internalModifiers)))) && - - (((Namespaces == null || !Namespaces.Any ()) && - (other.Namespaces == null || !other.Namespaces.Any ())) || - (Namespaces != null && other.Namespaces != null && - Namespaces.SequenceEqual (other.Namespaces))) && - - ElementType == other.ElementType && - ElementTypeName == other.ElementTypeName; - } - - - public override int GetHashCode () - { - unchecked { - return (internalModifiers != null? internalModifiers.SequenceHashCode () : 0) ^ - ElementType.GetHashCode () ^ - (Namespaces != null? Namespaces.SequenceHashCode () : 0) ^ - (ElementTypeName != null? ElementTypeName.GetHashCode () : 0); - } - } - - public override string ToString () - { - StringBuilder cppTypeString = new StringBuilder (); - - if (ElementType != CppTypes.Unknown && ElementType != CppTypes.Typename) - cppTypeString.Append (Enum.GetName (typeof (CppTypes), ElementType).ToLower ()).Append (' '); - - if (Namespaces != null) { - foreach (var ns in Namespaces) - cppTypeString.Append (ns).Append ("::"); - } - - if (ElementTypeName != null && ElementType != CppTypes.Typename) - cppTypeString.Append (ElementTypeName); - - if (internalModifiers != null) { - foreach (var modifier in internalModifiers) - cppTypeString.Append (' ').Append (modifier.ToString ()); - } - - return cppTypeString.ToString ().Trim (); - } - - public Type ToManagedType () - { - CppType me = this; - Type mappedType = (from checkType in CppTypeToManagedMap - where checkType (me) != null - select checkType (me)).FirstOrDefault (); - - return mappedType; - } - - public static CppType ForManagedType (Type type) - { - - CppType mappedType = (from checkType in ManagedToCppTypeMap - where checkType (type).ElementType != CppTypes.Unknown - select checkType (type)).FirstOrDefault (); - - return mappedType; - } - - public static CppType ForDelegate (Type delType) - { - if (!typeof (Delegate).IsAssignableFrom (delType)) - throw new ArgumentException ("Argument must be a delegate type"); - - throw new NotImplementedException (); - } - - public static implicit operator CppType (CppTypes type) { - return new CppType (type); - } - } -} - diff --git a/src/Mono.Cxxi/CppTypeInfo.cs b/src/Mono.Cxxi/CppTypeInfo.cs deleted file mode 100644 index afa7baeb..00000000 --- a/src/Mono.Cxxi/CppTypeInfo.cs +++ /dev/null @@ -1,430 +0,0 @@ -// -// Mono.Cxxi.CppTypeInfo.cs: Type metadata for C++ types -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// -// 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. - -using System; -using System.Linq; -using System.Reflection; -using System.Reflection.Emit; -using System.Collections.Generic; -using System.Collections.ObjectModel; - -using System.Runtime.InteropServices; - -using Mono.Cxxi.Abi; -using Mono.Cxxi.Util; - -namespace Mono.Cxxi { - - public enum BaseVirtualMethods { - - // Prepends this base's virtual methods to the primary vtable - PrependPrimary, - - // Appends this base's virtual methods to the primary vtable - AppendPrimary, - - // Creates a new out-of-band vtable for this base's virtual methods - NewVTable, - - } - - // NOTE: As AddBase is called, properties change. - // TypeComplete indicates when the dust has settled. - public class CppTypeInfo { - - public CppLibrary Library { get; private set; } - - public string TypeName { get; private set; } - public bool IsPrimaryBase { get; protected set; } // < True by default. set to False in cases where it is cloned as a non-primary base - - // returns the number of vtable slots reserved for the - // base class(es) before this class's virtual methods start - public int BaseVTableSlots { get; protected set; } - - public Type InterfaceType { get; private set; } - public Type NativeLayout { get; private set; } - public Type WrapperType { get; private set; } - - // read only versions: - public IList VirtualMethods { get; private set; } - public IList VTableDelegateTypes { get; private set; } - public IList VTableOverrides { get; private set; } - public IList BaseClasses { get; private set; } - - // backing lists: - protected List virtual_methods; - protected LazyGeneratedList vt_delegate_types; - protected LazyGeneratedList vt_overrides; - protected List base_classes; - - protected List vtable_index_adjustments; - - protected int native_size_without_padding; // <- this refers to the size of all the fields declared in the nativeLayout struct - protected int field_offset_padding_without_vtptr; - protected int gchandle_offset_delta; - - private VTable lazy_vtable; - - internal EmitInfo emit_info; // <- will be null when the type is done being emitted - public bool TypeComplete { get { return emit_info == null; } } - - #region Construction - - public CppTypeInfo (CppLibrary lib, string typeName, Type interfaceType, Type nativeLayout, Type/*?*/ wrapperType) - : this () - { - Library = lib; - TypeName = typeName; - - InterfaceType = interfaceType; - NativeLayout = nativeLayout; - WrapperType = wrapperType; - - virtual_methods = new List (Library.Abi.GetVirtualMethodSlots (this, interfaceType)); - VirtualMethods = new ReadOnlyCollection (virtual_methods); - - vt_delegate_types = new LazyGeneratedList (virtual_methods.Count, i => DelegateTypeCache.GetDelegateType (virtual_methods [i])); - VTableDelegateTypes = new ReadOnlyCollection (vt_delegate_types); - - vt_overrides = new LazyGeneratedList (virtual_methods.Count, i => Library.Abi.GetManagedOverrideTrampoline (this, i)); - VTableOverrides = new ReadOnlyCollection (vt_overrides); - - vtable_index_adjustments = new List (virtual_methods.Count); - - if (nativeLayout != null) - native_size_without_padding = nativeLayout.GetFields ().Any ()? Marshal.SizeOf (nativeLayout) : 0; - } - - protected CppTypeInfo () - { - base_classes = new List (); - BaseClasses = new ReadOnlyCollection (base_classes); - - field_offset_padding_without_vtptr = 0; - gchandle_offset_delta = 0; - IsPrimaryBase = true; - BaseVTableSlots = 0; - lazy_vtable = null; - - emit_info = new EmitInfo (); - } - - // The contract for Clone is that, if TypeComplete, working with the clone *through the public - // interface* is guaranteed not to affect the original. Note that any subclassses - // have access to protected stuff that is not covered by this guarantee. - public virtual CppTypeInfo Clone () - { - return this.MemberwiseClone () as CppTypeInfo; - } - - #endregion - - #region Type Layout - - public virtual int Alignment { - get { return IntPtr.Size; } - } - - // the extra padding to allocate at the top of the class before the fields begin - // (by default, just the vtable pointer) - public virtual int FieldOffsetPadding { - get { return field_offset_padding_without_vtptr + (virtual_methods.Count != 0? IntPtr.Size : 0); } - } - - public virtual int NativeSize { - get { - var basesize = native_size_without_padding + FieldOffsetPadding; - return basesize + (basesize % Alignment); - } - } - - public virtual int GCHandleOffset { - get { return NativeSize + gchandle_offset_delta; } - } - - - public void AddBase (CppTypeInfo baseType) - { - // by default, only the primary base shares the subclass's primary vtable - AddBase (baseType, base_classes.Count == 0 ? BaseVirtualMethods.PrependPrimary : BaseVirtualMethods.NewVTable); - } - - protected virtual void AddBase (CppTypeInfo baseType, BaseVirtualMethods location) - { - if (TypeComplete) - return; - - var baseVMethodCount = baseType.virtual_methods.Count; - baseType = baseType.Clone (); - - switch (location) { - - case BaseVirtualMethods.PrependPrimary: - - for (int i = 0; i < baseVMethodCount; i++) - virtual_methods.Insert (BaseVTableSlots + i, baseType.virtual_methods [i]); - - gchandle_offset_delta = baseType.gchandle_offset_delta; - - BaseVTableSlots += baseVMethodCount; - vt_delegate_types.Add (baseVMethodCount); - vt_overrides.Add (baseVMethodCount); - break; - - case BaseVirtualMethods.AppendPrimary: - - for (int i = 0; i < baseVMethodCount; i++) - virtual_methods.Add (baseType.virtual_methods [i]); - - gchandle_offset_delta = baseType.gchandle_offset_delta; - - vt_delegate_types.Add (baseVMethodCount); - vt_overrides.Add (baseVMethodCount); - break; - - case BaseVirtualMethods.NewVTable: - - baseType.IsPrimaryBase = (base_classes.Count == 0); - - // offset all previously added bases - foreach (var previousBase in base_classes) - previousBase.gchandle_offset_delta += baseType.NativeSize; - - // offset derived (this) type's gchandle - gchandle_offset_delta += baseType.GCHandleOffset; - - baseType.gchandle_offset_delta += native_size_without_padding + CountBases (b => !b.IsPrimaryBase) * IntPtr.Size; - - // ensure managed override tramps will be regenerated with correct gchandle offset - baseType.vt_overrides = new LazyGeneratedList (baseType.virtual_methods.Count, i => Library.Abi.GetManagedOverrideTrampoline (baseType, i)); - baseType.VTableOverrides = new ReadOnlyCollection (baseType.vt_overrides); - baseType.lazy_vtable = null; - break; - } - - base_classes.Add (baseType); - - field_offset_padding_without_vtptr += baseType.native_size_without_padding + - (location == BaseVirtualMethods.NewVTable? baseType.FieldOffsetPadding : baseType.field_offset_padding_without_vtptr); - } - - public virtual void CompleteType () - { - if (emit_info == null) - return; - - foreach (var baseClass in base_classes) - baseClass.CompleteType (); - - emit_info = null; - - RemoveVTableDuplicates (); - } - - public virtual CppType GetMangleType () - { - var mangleType = Library.Abi.GetMangleType (InterfaceType, InterfaceType); - mangleType.ElementTypeName = TypeName; - return mangleType; - } - - public int CountBases (Func predicate) - { - int count = 0; - foreach (var baseClass in base_classes) { - count += baseClass.CountBases (predicate); - count += predicate (baseClass)? 1 : 0; - } - return count; - } - - #endregion - - #region Casting - - protected virtual CppTypeInfo GetCastInfo (Type sourceType, Type targetType, out int offset) - { - offset = 0; - - if (WrapperType.Equals (targetType)) { - // check for downcast (base type -> this type) - - foreach (var baseClass in base_classes) { - if (baseClass.WrapperType.Equals (sourceType)) { - return baseClass; - } - offset -= baseClass.NativeSize; - } - - - } else if (WrapperType.IsAssignableFrom (sourceType)) { - // check for upcast (this type -> base type) - - foreach (var baseClass in base_classes) { - if (baseClass.WrapperType.Equals (targetType)) { - return baseClass; - } - offset += baseClass.NativeSize; - } - - } else { - throw new ArgumentException ("Either source type or target type must be equal to this wrapper type."); - } - - throw new InvalidCastException ("Cannot cast an instance of " + sourceType + " to " + targetType); - } - - public virtual CppInstancePtr Cast (ICppObject instance, Type targetType) - { - int offset; - var baseTypeInfo = GetCastInfo (instance.GetType (), targetType, out offset); - var result = new CppInstancePtr (instance.Native, offset); - - if (offset > 0 && instance.Native.IsManagedAlloc && baseTypeInfo.HasVTable) { - // we might need to paste the managed base-in-derived vtptr here --also inits native_vtptr - baseTypeInfo.VTable.InitInstance (ref result); - } - - return result; - } - - public virtual TTarget Cast (ICppObject instance) where TTarget : class - { - TTarget result; - var ptr = Cast (instance, typeof (TTarget)); - - // Check for existing instance based on vtable ptr - result = CppInstancePtr.ToManaged (ptr.Native); - - // Create a new wrapper if necessary - if (result == null) - result = Activator.CreateInstance (typeof (TTarget), ptr) as TTarget; - - return result; - } - - public virtual void InitNonPrimaryBase (ICppObject baseInDerived, ICppObject derived, Type baseType) - { - int offset; - var baseTypeInfo = GetCastInfo (derived.GetType (), baseType, out offset); - - Marshal.WriteIntPtr (baseInDerived.Native.Native, baseTypeInfo.GCHandleOffset, CppInstancePtr.MakeGCHandle (baseInDerived)); - } - - #endregion - - #region V-Table - - public virtual bool HasVTable { - get { return VirtualMethods.Any (); } - } - - public virtual VTable VTable { - get { - CompleteType (); - if (!HasVTable) - return null; - - if (lazy_vtable == null) - lazy_vtable = new VTable (this); - - return lazy_vtable; - } - } - - // the padding in the data pointed to by the vtable pointer before the list of function pointers starts - public virtual int VTableTopPadding { - get { return 0; } - } - - // the amount of extra room alloc'd after the function pointer list of the vtbl - public virtual int VTableBottomPadding { - get { return 0; } - } - - public virtual T GetAdjustedVirtualCall (CppInstancePtr instance, int derivedVirtualMethodIndex) - where T : class /* Delegate */ - { - var base_adjusted = BaseVTableSlots + derivedVirtualMethodIndex; - return VTable.GetVirtualCallDelegate (instance, base_adjusted + vtable_index_adjustments [base_adjusted]); - } - - protected virtual void RemoveVTableDuplicates () - { - // check that any virtual methods overridden in a subclass are only included once - var vsignatures = new Dictionary (MethodSignature.EqualityComparer); - var adjustment = 0; - - for (int i = 0; i < virtual_methods.Count; i++) { - vtable_index_adjustments.Add (adjustment); - - var sig = virtual_methods [i]; - if (sig == null) - continue; - - PInvokeSignature existing; - if (vsignatures.TryGetValue (sig, out existing)) { - OnVTableDuplicate (ref i, ref adjustment, sig, existing); - } else { - vsignatures.Add (sig, sig); - } - } - } - - protected virtual bool OnVTableDuplicate (ref int iter, ref int adj, PInvokeSignature sig, PInvokeSignature dup) - { - // This predicate ensures that duplicates are only removed - // if declared in different classes (i.e. overridden methods). - // We usually want to allow the same exact virtual methods to appear - // multiple times, in the case of nonvirtual diamond inheritance, for example. - if (!sig.OrigMethod.Equals (dup.OrigMethod)) { - virtual_methods.RemoveAt (iter--); - vt_overrides.Remove (1); - vt_delegate_types.Remove (1); - adj--; - return true; - } - - return false; - } - - #endregion - } - - // This is used internally by CppAbi: - internal class DummyCppTypeInfo : CppTypeInfo { - - public CppTypeInfo BaseTypeInfo { get; set; } - - protected override void AddBase (CppTypeInfo baseType, BaseVirtualMethods location) - { - BaseTypeInfo = baseType; - } - } -} - diff --git a/src/Mono.Cxxi/Interfaces.cs b/src/Mono.Cxxi/Interfaces.cs deleted file mode 100644 index f4a1765b..00000000 --- a/src/Mono.Cxxi/Interfaces.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// Mono.Cxxi.Interfaces.cs -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// -// 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. - -using System; -using Mono.Cxxi.Abi; - -namespace Mono.Cxxi { - - // The contract for ICppObject requires implementations to have the following constructors: - // + A public constructor that takes CppInstancePtr (native constructor) - // + A public constructor that takes CppTypeInfo, and as its sole operation, - // calls AddBase on that passed CppTypeInfo, passing its own typeinfo (subclass constructor) - // NOTE: It is important that the subclass constructor have no side effects. - // All constructors for wrappers of native subclasses must call the subclass constructor for the - // wrappers of their base class(es). - public interface ICppObject : IDisposable { - CppInstancePtr Native { get; } - } - - public interface ICppClass { - CppTypeInfo TypeInfo { get; } - } - - // This should go without saying, but the C++ class must have a constructor - // if it is to be instantiatable. - public interface ICppClassInstantiatable : ICppClass { - CppInstancePtr Alloc (); - } - - // It is recommended that managed wrappers implement ICppObject, but - // I'm not making it required so that any arbitrary object can be exposed to - // C++ via CppInstancePtr.ForManagedObject. - public interface ICppClassOverridable : ICppClassInstantiatable - /* where TManaged : ICppObject */ - { - CppInstancePtr Alloc (TManaged managed); - } -} diff --git a/src/Mono.Cxxi/Makefile.am b/src/Mono.Cxxi/Makefile.am deleted file mode 100644 index d343e0d8..00000000 --- a/src/Mono.Cxxi/Makefile.am +++ /dev/null @@ -1,102 +0,0 @@ - -EXTRA_DIST = m4/expansions.m4 - -if ENABLE_DEBUG -ASSEMBLY_COMPILER_COMMAND = $(GMCS) -ASSEMBLY_COMPILER_FLAGS = -noconfig -codepage:utf8 -warn:4 -optimize- -debug "-define:DEBUG" -BUILD_DIR = $(top_srcdir)/bin/Debug - -ASSEMBLY = $(BUILD_DIR)/Mono.Cxxi.dll -ASSEMBLY_MDB = $(ASSEMBLY).mdb - -MONO_CXXI_DLL_MDB=$(BUILD_DIR)/Mono.Cxxi.dll.mdb - -endif - -if ENABLE_RELEASE -ASSEMBLY_COMPILER_COMMAND = $(GMCS) -ASSEMBLY_COMPILER_FLAGS = -noconfig -codepage:utf8 -warn:4 -optimize+ -BUILD_DIR = $(top_srcdir)/bin/Release - -ASSEMBLY = $(BUILD_DIR)/Mono.Cxxi.dll -ASSEMBLY_MDB = - -MONO_VISUALC_INTEROP_DLL_MDB= - -endif - -COMPILE_TARGET = library -PROJECT_REFERENCES = - -AL=al2 -SATELLITE_ASSEMBLY_NAME=$(notdir $(basename $(ASSEMBLY))).resources.dll - -PROGRAMFILES = \ - $(MONO_CXXI_DLL_MDB) - -LINUX_PKGCONFIG = \ - $(MONO_CXXI_PC) - - -RESGEN=resgen2 - -all: $(ASSEMBLY) $(PROGRAMFILES) $(LINUX_PKGCONFIG) - -FILES = \ - Abi/CppAbi.cs \ - Abi/EmitInfo.cs \ - Abi/Impl/ItaniumAbi.cs \ - Abi/Impl/ItaniumTypeInfo.cs \ - Abi/Impl/MsvcAbi.cs \ - Abi/MethodType.cs \ - Abi/SymbolResolver.cs \ - Abi/VTable.cs \ - AssemblyInfo.cs \ - Attributes.cs \ - CppField.cs \ - CppInstancePtr.cs \ - CppLibrary.cs \ - CppModifiers.cs \ - CppType.cs \ - CppTypeInfo.cs \ - Interfaces.cs \ - Util/DelegateTypeCache.cs \ - Util/IEnumerableTransform.cs \ - Util/LazyGeneratedList.cs \ - Util/MethodSignature.cs \ - Util/ReflectionHelper.cs - -DATA_FILES = - -RESOURCES = - -EXTRAS = \ - Abi \ - Abi/Impl \ - Util \ - mono.cxxi.pc.in - -REFERENCES = \ - System \ - System.Core - -DLL_REFERENCES = - -CLEANFILES = $(PROGRAMFILES) $(LINUX_PKGCONFIG) - -include $(top_srcdir)/Makefile.include - -MONO_CXXI_PC = $(BUILD_DIR)/mono.cxxi.pc - -$(eval $(call emit-deploy-wrapper,MONO_CXXI_PC,mono.cxxi.pc)) - - -$(eval $(call emit_resgen_targets)) -$(build_xamlg_list): %.xaml.g.cs: %.xaml - xamlg '$<' - -$(ASSEMBLY_MDB): $(ASSEMBLY) - -$(ASSEMBLY): $(build_sources) $(build_resources) $(build_datafiles) $(DLL_REFERENCES) $(PROJECT_REFERENCES) $(build_xamlg_list) $(build_satellite_assembly_list) - mkdir -p $(shell dirname $(ASSEMBLY)) - $(ASSEMBLY_COMPILER_COMMAND) $(ASSEMBLY_COMPILER_FLAGS) -out:$(ASSEMBLY) -target:$(COMPILE_TARGET) $(build_sources_embed) $(build_resources_embed) $(build_references_ref) diff --git a/src/Mono.Cxxi/Mono.Cxxi.csproj b/src/Mono.Cxxi/Mono.Cxxi.csproj deleted file mode 100644 index 2bd138cf..00000000 --- a/src/Mono.Cxxi/Mono.Cxxi.csproj +++ /dev/null @@ -1,116 +0,0 @@ - - - - Debug - AnyCPU - 8.0.50727 - {4A864586-93C5-4DC1-8A80-F094A88506D7} - Library - 2.0 - Mono.Cxxi - v3.5 - - - - - 2.0 - http://localhost/Mono.VisualC.Interop/ - true - Web - true - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - true - false - true - - - true - full - false - ..\..\bin\Debug - DEBUG - prompt - 4 - false - Mono.Cxxi - AllRules.ruleset - - - none - false - bin\Release - prompt - 4 - false - CPPInterop - AllRules.ruleset - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Mono.Cxxi/Util/DelegateTypeCache.cs b/src/Mono.Cxxi/Util/DelegateTypeCache.cs deleted file mode 100644 index d5be361b..00000000 --- a/src/Mono.Cxxi/Util/DelegateTypeCache.cs +++ /dev/null @@ -1,92 +0,0 @@ -// -// Mono.Cxxi.Util.DelegateTypeCache.cs: Automatic delegate type creation and caching -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// -// 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. - -using System; -using System.Linq; -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.InteropServices; -using System.Collections.Generic; - -namespace Mono.Cxxi.Util { - - public static class DelegateTypeCache { - - private static Dictionary type_cache; - - public static Type GetDelegateType (MethodInfo signature, CallingConvention? callingConvention) - { - return GetDelegateType (ReflectionHelper.GetMethodParameterTypes (signature), signature.ReturnType, callingConvention); - } - public static Type GetDelegateType (IEnumerable parameterTypes, Type returnType, CallingConvention? callingConvention) - { - return GetDelegateType (new BasicSignature { ParameterTypes = parameterTypes.ToList (), ReturnType = returnType, CallingConvention = callingConvention }); - } - public static Type GetDelegateType (BasicSignature signature) - { - Type delegateType; - if (type_cache == null) - type_cache = new Dictionary (); - - if (!type_cache.TryGetValue (signature, out delegateType)) { - delegateType = CreateDelegateType (signature); - type_cache.Add (signature, delegateType); - } - - return delegateType; - } - - private static Type CreateDelegateType (BasicSignature signature) - { - string delTypeName = signature.UniqueName; - - TypeAttributes typeAttr = TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.AnsiClass | TypeAttributes.AutoClass; - TypeBuilder del = CppLibrary.interopModule.DefineType (delTypeName, typeAttr, typeof(MulticastDelegate)); - - if (signature.CallingConvention.HasValue) { - ConstructorInfo ufpa = typeof (UnmanagedFunctionPointerAttribute).GetConstructor (new Type [] { typeof (CallingConvention) }); - CustomAttributeBuilder unmanagedPointer = new CustomAttributeBuilder (ufpa, new object [] { signature.CallingConvention.Value }); - del.SetCustomAttribute (unmanagedPointer); - } - - MethodAttributes ctorAttr = MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public; - ConstructorBuilder ctor = del.DefineConstructor (ctorAttr, CallingConventions.Standard, new Type[] { typeof(object), typeof(System.IntPtr) }); - ctor.SetImplementationFlags (MethodImplAttributes.Runtime | MethodImplAttributes.Managed); - - Type [] parameterTypes = signature.ParameterTypes.ToArray (); - MethodAttributes methodAttr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual; - - MethodBuilder invokeMethod = del.DefineMethod ("Invoke", methodAttr, signature.ReturnType, parameterTypes); - invokeMethod.SetImplementationFlags (MethodImplAttributes.Runtime | MethodImplAttributes.Managed); - - return del.CreateType (); - } - } - -} - diff --git a/src/Mono.Cxxi/Util/IEnumerableTransform.cs b/src/Mono.Cxxi/Util/IEnumerableTransform.cs deleted file mode 100644 index 6bd54fc3..00000000 --- a/src/Mono.Cxxi/Util/IEnumerableTransform.cs +++ /dev/null @@ -1,645 +0,0 @@ -// -// Mono.Cxxi.Util.IEnumerableTransform.cs: Rule-based transformation for IEnumerable -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// -// 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. - -using System; -using System.Linq; -using System.Collections; -using System.Collections.Generic; - -namespace Mono.Cxxi.Util { - - - public static class IEnumerableTransform { - - // Transforms an IEnumerable into another by specific rules. - - public static IEnumerable Transform (this IEnumerable input, params EmitterFunc [] rules) - { - CloneableEnumerator enumerator = new CloneableEnumerator (input, 0); - - while (enumerator.MoveNext ()) { - InputData inputData = new InputData (input, enumerator); - - foreach (var rule in rules) { - TOut output; - if (rule (inputData.NewContext (), out output) == RuleResult.MatchEmit) - yield return output; - - } - } - - } - - public static IRule And (this IRule previousRules, IRule parentheticalRules) - { - return new AndRule (previousRules, parentheticalRules); - } - public static RuleCompound And (this IRule previousRules) - { - return new RuleCompound ((subsequentRules) => { - return And (previousRules, subsequentRules); - }); - } - - public static IRule Or (this IRule previousRules, IRule parentheticalRules) - { - return new OrRule (previousRules, parentheticalRules); - } - public static RuleCompound Or (this IRule previousRules) - { - return new RuleCompound ((subsequentRules) => { - return Or (previousRules, subsequentRules); - }); - } - - public static IRule After (this IRule previousRules, IRule parentheticalRules) - { - return new AndRule (new AfterRule (parentheticalRules), previousRules); - } - public static RuleCompound After (this IRule previousRules) - { - return new RuleCompound ((subsequentRules) => { - return After (previousRules, subsequentRules); - }); - } - - public static IRule AtEnd (this IRule previousRules) - { - return new AtEndRule (previousRules); - } - - public static EmitterFunc Emit (this IRule rule, Func result) - { - return delegate (InputData input, out TOut output) { - output = default (TOut); - TIn value = input.Value; - RuleResult ruleResult = rule.SatisfiedBy (input); - - if (ruleResult != RuleResult.NoMatch) { - input.MatchedRules.Add (rule); - output = result (value); - return ruleResult; - } - return RuleResult.NoMatch; - }; - } - public static EmitterFunc Emit (this IRule rule, TOut result) - { - return Emit (rule, (input) => result); - } - - // helpers: - - public static IEnumerable With (this IEnumerable current, T additionalValue) - { - foreach (var output in current) - yield return output; - yield return additionalValue; - } - - public static bool StartsWith (this IEnumerable current, IEnumerable beginning) - { - IEnumerator currentEnum = current.GetEnumerator (); - IEnumerator beginEnum = beginning.GetEnumerator (); - - while (currentEnum.MoveNext ()) { - if (!beginEnum.MoveNext ()) - return true; - - if (!currentEnum.Current.Equals (beginEnum.Current)) - return false; - } - return !beginEnum.MoveNext (); - } - - public static IEnumerable Without (this IEnumerable current, T unwantedValue) - { - foreach (var output in current) { - if (!output.Equals (unwantedValue)) - yield return output; - } - } - - public static IEnumerable WithoutFirst (this IEnumerable current, T unwantedValue) - { - bool first = true; - foreach (var output in current) { - if (first && output.Equals (unwantedValue)) - first = false; - else - yield return output; - } - } - - public static int SequenceHashCode (this IEnumerable sequence) - { - int hash = 0; - foreach (var item in sequence) - hash ^= item.GetHashCode (); - - return hash; - } - - // FIXME: Faster way to do this? - public static void AddFirst (this List list, IEnumerable items) - { - T [] temp = new T [list.Count]; - list.CopyTo (temp, 0); - list.Clear (); - list.AddRange (items); - list.AddRange (temp); - } - public static void AddFirst (this List list, T item) - { - list.Insert (0, item); - } - - - } - - public enum RuleResult { - NoMatch, - MatchEmit, - MatchNoEmit - } - - public delegate RuleResult EmitterFunc (InputData input, out TOut output); - - public struct InputData { - public IEnumerable AllValues; - public CloneableEnumerator Enumerator; - public List> MatchedRules; - public InputData (IEnumerable input, CloneableEnumerator enumerator) - { - this.AllValues = input; - this.Enumerator = enumerator; - this.MatchedRules = new List> (); - } - - public InputData NewContext () - { - InputData nctx = new InputData (); - nctx.AllValues = this.AllValues; - nctx.Enumerator = this.Enumerator.Clone (); - nctx.MatchedRules = this.MatchedRules; - return nctx; - } - - public TIn Value { - get { return Enumerator.Current; } - } - } - - #region Rules - public interface IRule { - RuleResult SatisfiedBy (InputData input); - } - - // yields all inputs indescriminately - public class AnyRule : IRule { - public AnyRule () - { - } - public RuleResult SatisfiedBy (InputData input) - { - return RuleResult.MatchEmit; - } - } - - // yields all inputs that haven't satisfied - // any other rule - public class UnmatchedRule : IRule { - public UnmatchedRule () - { - } - public RuleResult SatisfiedBy (InputData input) - { - return !input.MatchedRules.Any ()? RuleResult.MatchEmit : RuleResult.NoMatch; - } - } - - // yields input if it hasn't been satisfied before - public class FirstRule : IRule { - protected bool triggered = false; - public FirstRule () - { - } - public RuleResult SatisfiedBy (InputData input) - { - if (!triggered) { - triggered = true; - return RuleResult.MatchEmit; - } - return RuleResult.NoMatch; - } - } - - // yields input if it is the last that would satisfy - // all its matched rules - public class LastRule : IRule { - public LastRule () - { - } - public RuleResult SatisfiedBy (InputData input) - { - throw new NotImplementedException (); - } - } - - // yields input if the specified previous rule has already been satisfied - public class AfterRule : IRule { - protected IRule previousRule; - protected bool satisfied = false; - public AfterRule (IRule previousRule) - { - this.previousRule = previousRule; - } - public RuleResult SatisfiedBy (InputData input) - { - if (satisfied) - return RuleResult.MatchEmit; - - satisfied = previousRule.SatisfiedBy (input) != RuleResult.NoMatch; - - return RuleResult.NoMatch; - } - } - - // yields all inputs found in the specified set - public class InSetRule : IRule { - protected IEnumerable conditions; - - public InSetRule (params TIn [] conditions) - { - this.conditions = conditions; - } - public InSetRule (IEnumerable conditions) - { - this.conditions = conditions; - } - public RuleResult SatisfiedBy (InputData input) - { - return conditions.Contains (input.Value)? RuleResult.MatchEmit : RuleResult.NoMatch; - } - } - - public class PredicateRule : IRule { - protected Func predicate; - - public PredicateRule (Func predicate) - { - this.predicate = predicate; - } - public RuleResult SatisfiedBy (InputData input) - { - return predicate (input.Value)? RuleResult.MatchEmit : RuleResult.NoMatch; - } - } - - // is satisfied by any of the specified items as long the - // item appears adjacent with all the other items - public class AnyOrderRule : IRule { - protected IEnumerable conditions; - - protected Queue verifiedItems = new Queue (); - protected bool verified = false; - - - public AnyOrderRule (params TIn [] conditions) - { - this.conditions = conditions; - } - public AnyOrderRule (IEnumerable conditions) - { - this.conditions = conditions; - } - public RuleResult SatisfiedBy (InputData inputData) - { - if (verified && verifiedItems.Count > 0) { - verifiedItems.Dequeue (); - return RuleResult.MatchNoEmit; - } else - verified = false; - - IEnumerator input = inputData.Enumerator; - - while (conditions.Contains (input.Current) && !verifiedItems.Contains (input.Current)) { - verifiedItems.Enqueue (input.Current); - if (!input.MoveNext ()) break; - } - - if (verifiedItems.Count == conditions.Count ()) { - verified = true; - verifiedItems.Dequeue (); - return RuleResult.MatchEmit; - } else - verifiedItems.Clear (); - - return RuleResult.NoMatch; - } - } - - public class InOrderRule : IRule { - protected IEnumerable conditions; - - protected bool verified = false; - protected int verifiedCount = 0; - - public InOrderRule (params TIn [] conditions) - { - this.conditions = conditions; - } - public InOrderRule (IEnumerable conditions) - { - this.conditions = conditions; - } - public RuleResult SatisfiedBy (InputData inputData) - { - if (verified && verifiedCount > 0) { - verifiedCount--; - return RuleResult.MatchNoEmit; - } else - verified = false; - - IEnumerator condition = conditions.GetEnumerator (); - IEnumerator input = inputData.Enumerator; - - while (condition.MoveNext () && condition.Equals (input.Current)) { - verifiedCount++; - if (!input.MoveNext ()) break; - } - if (verifiedCount == conditions.Count ()) { - verified = true; - verifiedCount--; - return RuleResult.MatchEmit; - } else - verifiedCount = 0; - - return RuleResult.NoMatch; - } - } - - // yields all inputs that match all specified rules - public class AndRule : IRule { - protected IEnumerable> rules; - - public AndRule (IEnumerable> rules) - { - this.rules = rules; - } - public AndRule (params IRule[] rules) - { - this.rules = rules; - } - public RuleResult SatisfiedBy (InputData input) - { - RuleResult finalResult = RuleResult.NoMatch; - foreach (var rule in rules) { - RuleResult result = rule.SatisfiedBy (input.NewContext ()); - if (result == RuleResult.NoMatch) - return RuleResult.NoMatch; - if (finalResult != RuleResult.MatchNoEmit) - finalResult = result; - - input.MatchedRules.Add (rule); - } - return finalResult; - } - } - - // yields all inputs that match any specified rules - public class OrRule : IRule { - protected IEnumerable> rules; - - public OrRule (IEnumerable> rules) - { - this.rules = rules; - } - public OrRule (params IRule[] rules) - { - this.rules = rules; - } - public RuleResult SatisfiedBy (InputData input) - { - foreach (var rule in rules) { - RuleResult result = rule.SatisfiedBy (input.NewContext ()); - if (result != RuleResult.NoMatch) { - input.MatchedRules.Add (rule); - return result; - } - } - - return RuleResult.NoMatch; - } - } - - public class AtEndRule : IRule { - protected IRule rule; - - public AtEndRule (IRule rule) - { - this.rule = rule; - } - public RuleResult SatisfiedBy (InputData input) - { - RuleResult rr = rule.SatisfiedBy (input); - if (!input.Enumerator.MoveNext ()) - return rr; - return RuleResult.NoMatch; - } - } - #endregion - - // the base point for building up rules - // All rules start For... - public static class For { - - public static IRule AnyInputIn (params TIn [] input) - { - return new InSetRule (input); - } - public static IRule AnyInputIn (IEnumerable input) - { - return new InSetRule (input); - } - - public static SequenceQualifier AllInputsIn (params TIn [] input) - { - return new SequenceQualifier (input, null); - } - public static SequenceQualifier AllInputsIn (IEnumerable input) - { - return new SequenceQualifier (input, null); - } - - public static RuleCompound First () - { - return new RuleCompound ((subsequentRules) => { - return new AndRule (subsequentRules, new FirstRule ()); - }); - } - - public static RuleCompound Last () - { - return new RuleCompound ((subsequentRules) => { - return new AndRule (subsequentRules, new LastRule ()); - }); - } - - public static IRule InputsWhere (Func predicate) - { - return new PredicateRule (predicate); - } - - public static IRule AnyInput () - { - return new AnyRule (); - } - public static IRule UnmatchedInput () - { - return new UnmatchedRule (); - } - } - - public class RuleCompound { - protected Func,IRule> additionalRuleCallback; - - public RuleCompound (Func,IRule> additionalRuleCallback) - { - this.additionalRuleCallback = additionalRuleCallback; - } - - public SequenceQualifier AllInputsIn (params TIn [] input) - { - return new SequenceQualifier (input, additionalRuleCallback); - } - public SequenceQualifier AllInputsIn (IEnumerable input) - { - return new SequenceQualifier (input, additionalRuleCallback); - } - - public IRule AnyInputIn (params TIn[] input) - { - return additionalRuleCallback (new InSetRule (input)); - } - public IRule AnyInputIn (IEnumerable input) - { - return additionalRuleCallback (new InSetRule (input)); - } - - public IRule InputsWhere (Func predicate) - { - return additionalRuleCallback (new PredicateRule (predicate)); - } - - public IRule AnyInput () - { - return additionalRuleCallback (new AnyRule ()); - } - } - - public class SequenceQualifier { - protected IEnumerable sequence; - protected Func, IRule> additionalRuleCallback; - - public SequenceQualifier (IEnumerable sequence, Func, IRule> additionalRuleCallback) - { - this.sequence = sequence; - this.additionalRuleCallback = additionalRuleCallback ?? (rul => rul); - } - - public IRule InThatOrder () - { - return additionalRuleCallback (new InOrderRule (sequence)); - } - - public IRule InAnyOrder () - { - return additionalRuleCallback (new AnyOrderRule (sequence)); - } - } - - public static class Choose { - - public static EmitterFunc TopOne (params EmitterFunc [] rules) - { - return delegate (InputData input, out TOut output) { - output = default (TOut); - foreach (var rule in rules) { - RuleResult result = rule (input.NewContext (), out output); - if (result != RuleResult.NoMatch) - return result; - } - return RuleResult.NoMatch; - }; - } - } - - public class CloneableEnumerator : IEnumerator { - private IEnumerable wrappedEnumerable; - private IEnumerator wrappedEnumerator; - - private int position; - - public CloneableEnumerator (IEnumerable enumerable, int position) - { - this.wrappedEnumerable = enumerable; - this.position = position; - - this.wrappedEnumerator = wrappedEnumerable.GetEnumerator (); - for (int i = 0; i < position; i++) - wrappedEnumerator.MoveNext (); - } - - public CloneableEnumerator Clone () { - return new CloneableEnumerator (this.wrappedEnumerable, this.position); - } - - public void Reset () - { - wrappedEnumerator.Reset (); - } - - public bool MoveNext () - { - position++; - return wrappedEnumerator.MoveNext (); - } - - public T Current { - get { return wrappedEnumerator.Current; } - } - object IEnumerator.Current { - get { return this.Current; } - } - public void Dispose () - { - } - } -} - diff --git a/src/Mono.Cxxi/Util/LazyGeneratedList.cs b/src/Mono.Cxxi/Util/LazyGeneratedList.cs deleted file mode 100644 index 45d4be90..00000000 --- a/src/Mono.Cxxi/Util/LazyGeneratedList.cs +++ /dev/null @@ -1,126 +0,0 @@ -// -// Mono.Cxxi.Util.LazyGeneratedList.cs: A list whose items are generated and cached on first access -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// -// 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. - -using System; -using System.Collections; -using System.Collections.Generic; - -namespace Mono.Cxxi.Util { - - public class LazyGeneratedList : IList - where TItem : class - { - private TItem [] cache; - private Func generator; - - private int count; - - public LazyGeneratedList (int count, Func generator) - { - this.cache = new TItem [count]; - this.generator = generator; - this.count = count; - } - - public IEnumerator GetEnumerator () - { - for (int i = 0; i < Count; i++) - yield return this [i]; - } - IEnumerator IEnumerable.GetEnumerator () - { - return this.GetEnumerator (); - } - - public int Count { - get { return count; } - } - - public bool IsReadOnly { - get { return true; } - } - - public TItem this [int i] { - get { - // access to cache [i] will throw the IndexOutOfRange exception for us - return cache [i] == null? (cache [i] = generator (i)) : cache [i]; - } - set { - throw new NotSupportedException ("This IList is read only"); - } - } - - public void Add (int count) - { - this.count += count; - // flush cache - cache = new TItem [this.count]; - } - public void Remove (int count) - { - this.count -= count; - // flush cache - cache = new TItem [this.count]; - } - - // FIXME: Should probably implement these at some point - public bool Contains (TItem item) - { - throw new NotImplementedException (); - } - public void CopyTo (TItem[] array, int arrayIndex) - { - throw new NotImplementedException (); - } - public int IndexOf (TItem item) - { - throw new NotImplementedException (); - } - public void Insert (int index, TItem item) - { - throw new NotImplementedException (); - } - public void RemoveAt (int index) - { - throw new NotImplementedException (); - } - public void Add (TItem item) - { - throw new NotImplementedException (); - } - public void Clear () - { - throw new NotImplementedException (); - } - public bool Remove (TItem item) - { - throw new NotImplementedException (); - } - } -} - diff --git a/src/Mono.Cxxi/Util/MethodSignature.cs b/src/Mono.Cxxi/Util/MethodSignature.cs deleted file mode 100644 index 10395b25..00000000 --- a/src/Mono.Cxxi/Util/MethodSignature.cs +++ /dev/null @@ -1,145 +0,0 @@ -// -// Mono.Cxxi.Util.MethodSignature.cs: Hash-friendly structs to represent arbitrary method and delegate signatures -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// -// 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. - -using System; -using System.Linq; -using System.Text; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Collections.Generic; - -using Mono.Cxxi.Abi; - -namespace Mono.Cxxi.Util { - - public class BasicSignature { - public CallingConvention? CallingConvention { get; set; } - public List ParameterTypes { get; set; } - public Type ReturnType { get; set; } - - private string uniqueName; - - public string UniqueName { - get { - if (uniqueName != null) - return uniqueName; - - StringBuilder sb = new StringBuilder ("_"); - - if (CallingConvention.HasValue) - sb.Append (Enum.GetName (typeof (CallingConvention), CallingConvention.Value)); - - sb.Append ('_').Append (ReturnType.Name); - - if (ParameterTypes == null) - return uniqueName = sb.ToString (); - - foreach (var param in ParameterTypes) - sb.Append ('_').Append (param.Name); - - return uniqueName = sb.ToString (); - } - } - - public bool IsCompatibleWith (BasicSignature other) - { - return CallingConvention == other.CallingConvention && - ((ParameterTypes == null && other.ParameterTypes == null) || - ParameterTypes.SequenceEqual (other.ParameterTypes)) && - ReturnType.Equals (other.ReturnType); - } - - public override bool Equals (object obj) - { - var other = obj as BasicSignature; - if (other == null) - return false; - - return IsCompatibleWith (other); - } - - public override int GetHashCode () - { - unchecked { - return CallingConvention.GetHashCode () ^ - (ParameterTypes != null? ParameterTypes.SequenceHashCode () : 0) ^ - ReturnType.GetHashCode (); - } - } - } - - public class MethodSignature : BasicSignature { - public static readonly IEqualityComparer EqualityComparer = new MethodSignatureEqualityComparer (); - - public string Name { get; set; } - public MethodType Type { get; set; } - - public new bool Equals (object obj) - { - var other = obj as MethodSignature; - if (other == null) - return false; - - return IsCompatibleWith (other) && - Type == other.Type && - (Name.Equals (other.Name) || Type != MethodType.Native); - } - - - public new int GetHashCode () - { - unchecked { - return base.GetHashCode () ^ - Type.GetHashCode () ^ - (Type == MethodType.Native? Name.GetHashCode () : 0); - } - } - - private class MethodSignatureEqualityComparer : IEqualityComparer { - public bool Equals (MethodSignature x, MethodSignature y) - { - return x.Equals (y); - } - public int GetHashCode (MethodSignature obj) - { - return obj.GetHashCode (); - } - } - - public override string ToString () - { - return string.Format ("[{0} {1} ({2})]", ReturnType.Name, Name, string.Join (", ", ParameterTypes.Select (t => t.Name).ToArray ())); - } - } - - public class PInvokeSignature : MethodSignature { - // The original c# method this signature was generated from - public MethodInfo OrigMethod; - } -} - diff --git a/src/Mono.Cxxi/Util/ReflectionHelper.cs b/src/Mono.Cxxi/Util/ReflectionHelper.cs deleted file mode 100644 index ba92da2a..00000000 --- a/src/Mono.Cxxi/Util/ReflectionHelper.cs +++ /dev/null @@ -1,118 +0,0 @@ -// -// Mono.Cxxi.Util.ReflectionHelper.cs: Helper methods for common reflection API tasks -// -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010-2011 Alexander Corrado -// -// 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. - -using System; -using System.Linq; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Reflection; -using System.Reflection.Emit; - -namespace Mono.Cxxi.Util { - internal static class ReflectionHelper { - - public static MethodInfo GetMethodInfoForDelegate (Type delType) - { - return delType.GetMethod ("Invoke"); - } - - public static Type[] GetDelegateParameterTypes (Type delType) - { - MethodInfo invoke = GetMethodInfoForDelegate (delType); - if (invoke == null) - return null; - - return GetMethodParameterTypes (invoke); - } - - public static Type[] GetMethodParameterTypes (MethodInfo method) - { - ParameterInfo[] parameters = method.GetParameters (); - Type[] parameterTypes = new Type [parameters.Length]; - - for (int i = 0; i < parameters.Length; i++) - parameterTypes [i] = parameters [i].ParameterType; - - return parameterTypes; - } - - public static void ApplyMethodParameterAttributes (MethodInfo source, MethodBuilder target, bool forPInvoke) - { - ParameterInfo[] parameters = source.GetParameters (); - foreach (var param in parameters) - ApplyAttributes (param, target.DefineParameter, forPInvoke); - } - - public static void ApplyMethodParameterAttributes (MethodInfo source, DynamicMethod target, bool forPInvoke) - { - ParameterInfo[] parameters = source.GetParameters (); - foreach (var param in parameters) - ApplyAttributes (param, target.DefineParameter, forPInvoke); - } - - public static ParameterBuilder ApplyAttributes (ParameterInfo param, Func makePB, bool forPInvoke) - { - ParameterAttributes attr = param.Attributes; - CustomAttributeBuilder marshalAsAttr = null; - - MarshalAsAttribute existingMarshalAs = param.GetCustomAttributes (typeof (MarshalAsAttribute), - false).FirstOrDefault () as MarshalAsAttribute; - - /* if (forPInvoke && - typeof (ICppObject).IsAssignableFrom (param.ParameterType) && - !param.ParameterType.Equals (typeof (CppInstancePtr)) && - existingMarshalAs == null) - { - ConstructorInfo ctor = typeof (MarshalAsAttribute).GetConstructor (new Type[] { typeof (UnmanagedType) }); - object[] args = new object [] { UnmanagedType.CustomMarshaler }; - FieldInfo[] fields = new FieldInfo [] { typeof (MarshalAsAttribute).GetField("MarshalTypeRef") }; - object[] values = new object [] { typeof (CppObjectMarshaler) }; - - marshalAsAttr = new CustomAttributeBuilder (ctor, args, fields, values); - attr = attr | ParameterAttributes.HasFieldMarshal; - } else */ if (forPInvoke && existingMarshalAs != null) { - // FIXME: This still doesn't feel like it's working right.. especially for virtual functions - ConstructorInfo ctor = typeof (MarshalAsAttribute).GetConstructor (new Type[] { typeof (UnmanagedType) }); - object[] args = new object [] { existingMarshalAs.Value }; - - var fields = from field in typeof (MarshalAsAttribute).GetFields () - where field.GetValue (existingMarshalAs) != null - select field; - - var values = from field in fields select field.GetValue (existingMarshalAs); - - marshalAsAttr = new CustomAttributeBuilder (ctor, args, fields.ToArray (), values.ToArray ()); - attr = attr | ParameterAttributes.HasFieldMarshal; - } - - ParameterBuilder pb = makePB (param.Position, attr, param.Name); - if (marshalAsAttr != null) pb.SetCustomAttribute (marshalAsAttr); - return pb; - } - } -} diff --git a/src/Mono.Cxxi/mono.cxxi.pc.in b/src/Mono.Cxxi/mono.cxxi.pc.in deleted file mode 100644 index 8aaa4255..00000000 --- a/src/Mono.Cxxi/mono.cxxi.pc.in +++ /dev/null @@ -1,6 +0,0 @@ -Name: Mono.Cxxi -Description: C++ interoperability for managed code -Version: 0.1 - -Requires: -Libs: -r:@expanded_libdir@/@PACKAGE@/Mono.Cxxi.dll