public DelegateCaller(MethodDesc method, DelegateWrapperDeclaration container) : base(container, 0) { DelegateDeclaration delegateDeclaration = new DelegateDeclaration(container.Type, container, container.AccessModifier); string returnDecl = MethodDeclaration.GetReturnValue(method); IEnumerable <string> argumentNames = MethodDeclaration.GetParameterNames(method); WriteLine(() => "{"); WriteLine(() => " if (reference == IntPtr.Zero)"); WriteLine(() => " throw new InvalidComObjectException();"); WriteLine(() => " Delegate genericDelegate = Marshal.GetDelegateForFunctionPointer(reference, typeof(" + delegateDeclaration.DelegateTypeName + "));"); WriteLine(() => " " + delegateDeclaration.DelegateTypeName + " method = (" + delegateDeclaration.DelegateTypeName + ")genericDelegate;"); WriteLine(() => " " + ((returnDecl == "void") ? "" : "return ") + "method(" + string.Join(", ", argumentNames) + ");"); WriteLine(() => "}"); }
public DelegateCaller(int index, MethodDesc method, InterfaceWrapperDeclaration container) : base(container, 0) { string delegateName = container.GetDelegateName(index); string vtblMethodName = container.GetMethodName(index); string returnDecl = MethodDeclaration.GetReturnValue(method); IEnumerable <string> argumentNames = MethodDeclaration.GetParameterNames(method); WriteLine(() => "{"); WriteLine(() => " " + container.vtbl.TypeName + "** @this = (" + container.vtbl.TypeName + "**)reference;"); WriteLine(() => " " + container.vtbl.TypeName + "* vtbl = *@this;"); WriteLine(() => " if (vtbl == null)"); WriteLine(() => " throw new InvalidComObjectException();"); WriteLine(() => " Delegate genericDelegate = Marshal.GetDelegateForFunctionPointer(vtbl->" + vtblMethodName + ", typeof(" + delegateName + "));"); WriteLine(() => " " + delegateName + " method = (" + delegateName + ")genericDelegate;"); WriteLine(() => " " + ((returnDecl == "void") ? "" : "return ") + "method(" + string.Join(", ", new string[] { "@this" }.Union(argumentNames)) + ");"); WriteLine(() => "}"); }
public InterfaceWrapperDeclaration(TypeDesc type, TextBlock container, AccessModifierType accessModifier) : base(type, container, accessModifier) { isIUnknown = type.BaseTypes.Any(x => x.Name == "IUnknown"); isUserImplemented = InterfaceDeclaration.IsUserImplemented(type); ignoreIdentifier = InterfaceDeclaration.IsWithoutIdentifier(type); var methods = type.AllMethods.ToArray(); vtbl = new InterfaceVtblDeclaration(type, this); WriteBaseLine(() => "{"); AddTextBlock(vtbl); WriteLine(); for (int i = 0; i < methods.Length; i++) { int index = i; MethodDesc method = type.AllMethods.ToArray()[i]; string parameters = vtbl.TypeName + "** @this"; if (MethodDeclaration.GetParameterNames(method).Any()) { parameters += ", " + MethodDeclaration.GetParameters(method); } WriteLine(() => "private unsafe delegate " + MethodDeclaration.GetReturnValue(method) + " " + GetDelegateName(index) + "(" + parameters + ");"); } WriteLine(); WriteLine(() => "private readonly void* reference;"); if (!ignoreIdentifier) { WriteLine(() => "private static readonly Guid iid = new Guid(\"" + type.CLSID.ToString() + "\");"); WriteLine(); WriteLine(() => AccessModifier + " static unsafe Guid IID"); WriteLine(() => "{"); WriteLine(() => " get"); WriteLine(() => " {"); WriteLine(() => " return iid;"); WriteLine(() => " }"); WriteLine(() => "}"); } for (int i = 0; i < methods.Length; i++) { WriteLine(); bool isNew = ((methods[i].Name == "GetType" || methods[i].Name == "ToString") && !methods[i].Parameters.Any()); AddTextBlock(new MethodDeclaration(methods[i], this, AccessModifierType.Public, isNew, new DelegateCaller(i, methods[i], this))); } if (isIUnknown) { WriteLine(); WriteLine(() => "void IDisposable.Dispose()"); WriteLine(() => "{"); WriteLine(() => " while ((reference != null) && (Release() > 0))"); WriteLine(() => " {"); WriteLine(() => " }"); WriteLine(() => "}"); } WriteLine(); WriteLine(() => AccessModifier + " unsafe " + TypeName + "(IntPtr value)"); WriteLine(() => "{"); WriteLine(() => " reference = (void*)value;"); WriteLine(() => "}"); WriteLine(); WriteLine(() => AccessModifier + " unsafe " + TypeName + "(void* value)"); WriteLine(() => "{"); WriteLine(() => " reference = value;"); WriteLine(() => "}"); foreach (string baseTypeRefName in type.BaseTypes.Where(x => !InterfaceDeclaration.IsSpecialInterface(x)).Select(x => x.Name)) { WriteLine(); WriteLine(() => "public static unsafe explicit operator " + TypeName + "(" + baseTypeRefName + " value)"); WriteLine(() => "{"); WriteLine(() => " return new " + TypeName + "(*((void**)(&value)));"); WriteLine(() => "}"); WriteLine(); WriteLine(() => "public static unsafe implicit operator " + baseTypeRefName + "(" + TypeName + " value)"); WriteLine(() => "{"); WriteLine(() => " return new " + baseTypeRefName + "(value.reference);"); WriteLine(() => "}"); } WriteLine(); WriteLine(() => "public static unsafe implicit operator IntPtr(" + TypeName + " value)"); WriteLine(() => "{"); WriteLine(() => " return new IntPtr(value.reference);"); WriteLine(() => "}"); WriteLine(); WriteLine(() => "public static unsafe implicit operator void*(" + TypeName + " value)"); WriteLine(() => "{"); WriteLine(() => " return value.reference;"); WriteLine(() => "}"); WriteLine(); WriteLine(() => "public static unsafe implicit operator " + TypeName + "(IntPtr value)"); WriteLine(() => "{"); WriteLine(() => " return new " + TypeName + "(value);"); WriteLine(() => "}"); WriteLine(); WriteLine(() => "public static unsafe implicit operator " + TypeName + "(void* value)"); WriteLine(() => "{"); WriteLine(() => " return new " + TypeName + "(value);"); WriteLine(() => "}"); WriteLine(); WriteLine(() => "public unsafe override bool Equals(object obj)"); WriteLine(() => "{"); WriteLine(() => " " + TypeName + " other = (" + TypeName + ")obj;"); WriteLine(() => " return reference == other.reference;"); WriteLine(() => "}"); WriteLine(); WriteLine(() => "public unsafe override int GetHashCode()"); WriteLine(() => "{"); WriteLine(() => " return new IntPtr(reference).GetHashCode();"); WriteLine(() => "}"); WriteLine(); WriteLine(() => "public unsafe static bool operator ==(" + TypeName + " left, " + TypeName + " right)"); WriteLine(() => "{"); WriteLine(() => " return left.reference == right.reference;"); WriteLine(() => "}"); WriteLine(); WriteLine(() => "public unsafe static bool operator !=(" + TypeName + " left, " + TypeName + " right)"); WriteLine(() => "{"); WriteLine(() => " return left.reference != right.reference;"); WriteLine(() => "}"); WriteBaseLine(() => "}"); }