Browse Source

Fixed several issues related to [MarshalAs] attributes.

pull/194/merge
Daniel Grunwald 14 years ago
parent
commit
2d42dd5c57
  1. 39
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 41
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  3. 1
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  4. 1
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  5. 87
      ICSharpCode.Decompiler/Tests/PInvoke.cs
  6. 6
      ICSharpCode.Decompiler/Tests/TestRunner.cs

39
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -801,7 +801,13 @@ namespace ICSharpCode.Decompiler.Ast @@ -801,7 +801,13 @@ namespace ICSharpCode.Decompiler.Ast
astProp.Setter.Body = CreateMethodBody(propDef.SetMethod);
astProp.Setter.AddAnnotation(propDef.SetMethod);
ConvertAttributes(astProp.Setter, propDef.SetMethod);
ConvertCustomAttributes(astProp.Setter, propDef.SetMethod.Parameters.Last(), "param");
ParameterDefinition lastParam = propDef.SetMethod.Parameters.LastOrDefault();
if (lastParam != null) {
ConvertCustomAttributes(astProp.Setter, lastParam, "param");
if (lastParam.HasMarshalInfo) {
astProp.Setter.Attributes.Add(new AttributeSection(ConvertMarshalInfo(lastParam, propDef.Module)) { AttributeTarget = "param" });
}
}
if ((setterModifiers & Modifiers.VisibilityMask) != (astProp.Modifiers & Modifiers.VisibilityMask))
astProp.Setter.Modifiers = setterModifiers & Modifiers.VisibilityMask;
@ -1170,6 +1176,37 @@ namespace ICSharpCode.Decompiler.Ast @@ -1170,6 +1176,37 @@ namespace ICSharpCode.Decompiler.Ast
Ast.Attribute attr = CreateNonCustomAttribute(typeof(MarshalAsAttribute), module);
var unmanagedType = new TypeReference("System.Runtime.InteropServices", "UnmanagedType", module, module.TypeSystem.Corlib);
attr.Arguments.Add(MakePrimitive((int)marshalInfo.NativeType, unmanagedType));
FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo;
if (fami != null) {
attr.AddNamedArgument("SizeConst", new PrimitiveExpression(fami.Size));
if (fami.ElementType != NativeType.None)
attr.AddNamedArgument("ArraySubType", MakePrimitive((int)fami.ElementType, unmanagedType));
}
SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo;
if (sami != null && sami.ElementType != VariantType.None) {
var varEnum = new TypeReference("System.Runtime.InteropServices", "VarEnum", module, module.TypeSystem.Corlib);
attr.AddNamedArgument("SafeArraySubType", MakePrimitive((int)sami.ElementType, varEnum));
}
ArrayMarshalInfo ami = marshalInfo as ArrayMarshalInfo;
if (ami != null) {
if (ami.ElementType != NativeType.Max)
attr.AddNamedArgument("ArraySubType", MakePrimitive((int)ami.ElementType, unmanagedType));
if (ami.Size >= 0)
attr.AddNamedArgument("SizeConst", new PrimitiveExpression(ami.Size));
if (ami.SizeParameterMultiplier != 0)
attr.AddNamedArgument("SizeParamIndex", new PrimitiveExpression(ami.SizeParameterIndex));
}
CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo;
if (cmi != null) {
attr.AddNamedArgument("MarshalType", new PrimitiveExpression(cmi.ManagedType.FullName));
if (!string.IsNullOrEmpty(cmi.Cookie))
attr.AddNamedArgument("MarshalCookie", new PrimitiveExpression(cmi.Cookie));
}
FixedSysStringMarshalInfo fssmi = marshalInfo as FixedSysStringMarshalInfo;
if (fssmi != null) {
attr.AddNamedArgument("SizeConst", new PrimitiveExpression(fssmi.Size));
}
return attr;
}
#endregion

41
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -269,8 +269,18 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -269,8 +269,18 @@ namespace ICSharpCode.Decompiler.Disassembler
ArrayMarshalInfo ami = (ArrayMarshalInfo)marshalInfo;
if (ami == null)
goto default;
WriteNativeType(ami.ElementType);
output.Write("[size={0}, sizeParameterIndex={1}, sizeParameterMultiplier={2}]", ami.Size, ami.SizeParameterIndex, ami.SizeParameterMultiplier);
if (ami.ElementType != NativeType.Max)
WriteNativeType(ami.ElementType);
output.Write('[');
if (ami.SizeParameterMultiplier == 0) {
output.Write(ami.Size.ToString());
} else {
if (ami.Size >= 0)
output.Write(ami.Size.ToString());
output.Write(" + ");
output.Write(ami.SizeParameterIndex.ToString());
}
output.Write(']');
break;
case NativeType.Currency:
output.Write("currency");
@ -370,10 +380,15 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -370,10 +380,15 @@ namespace ICSharpCode.Decompiler.Disassembler
}
break;
case NativeType.FixedArray:
output.Write("fixed sysstring");
output.Write("fixed array");
FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo;
if (fami != null)
output.Write("[{0}]", ((FixedArrayMarshalInfo)marshalInfo).Size);
if (fami != null) {
output.Write("[{0}]", fami.Size);
if (fami.ElementType != NativeType.None) {
output.Write(' ');
WriteNativeType(fami.ElementType);
}
}
break;
case NativeType.ByValStr:
output.Write("byvalstr");
@ -395,12 +410,19 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -395,12 +410,19 @@ namespace ICSharpCode.Decompiler.Disassembler
break;
case NativeType.CustomMarshaler:
CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo;
goto default; // ???
if (cmi == null)
goto default;
output.Write("custom(\"{0}\", \"{1}\"",
NRefactory.CSharp.OutputVisitor.ConvertString(cmi.ManagedType.FullName),
NRefactory.CSharp.OutputVisitor.ConvertString(cmi.Cookie));
if (cmi.Guid != Guid.Empty || !string.IsNullOrEmpty(cmi.UnmanagedType)) {
output.Write(", \"{0}\", \"{1}\"", cmi.Guid.ToString(), NRefactory.CSharp.OutputVisitor.ConvertString(cmi.UnmanagedType));
}
output.Write(')');
break;
case NativeType.Error:
output.Write("error");
break;
case NativeType.Max:
// ???
default:
output.Write(nativeType.ToString());
break;
@ -420,6 +442,9 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -420,6 +442,9 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write("[opt] ");
p.ParameterType.WriteTo(output);
output.Write(' ');
if (p.HasMarshalInfo) {
WriteMarshalInfo(p.MarshalInfo);
}
output.WriteDefinition(DisassemblerHelpers.Escape(p.Name), p);
if (i < parameters.Count - 1)
output.Write(',');

1
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -370,7 +370,6 @@ namespace ICSharpCode.Decompiler.ILAst @@ -370,7 +370,6 @@ namespace ICSharpCode.Decompiler.ILAst
} else if (expr.Code == ILCode.Newobj && expr.Arguments.Count == 2) {
// Might be 'newobj(SomeDelegate, target, ldvirtftn(F, target))'.
ILVariable target;
ILExpression ldvirtftnArg;
if (expr.Arguments[0].Match(ILCode.Ldloc, out target)
&& expr.Arguments[1].Code == ILCode.Ldvirtftn
&& expr.Arguments[1].Arguments.Count == 1

1
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -59,6 +59,7 @@ @@ -59,6 +59,7 @@
<Compile Include="CheckedUnchecked.cs" />
<Compile Include="Helpers\CodeAssert.cs" />
<Compile Include="IncrementDecrement.cs" />
<Compile Include="PInvoke.cs" />
<Compile Include="QueryExpressions.cs" />
<Compile Include="Switch.cs" />
<Compile Include="UndocumentedExpressions.cs" />

87
ICSharpCode.Decompiler/Tests/PInvoke.cs

@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// 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;
// P/Invoke and marshalling attribute tests
public class PInvoke
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 2)]
public struct MarshalAsTest
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public uint[] FixedArray;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.Bool)]
public int[] FixedBoolArray;
[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
public string[] SafeBStrArray;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string FixedString;
}
[StructLayout(LayoutKind.Explicit)]
public struct Rect
{
[FieldOffset(0)]
public int left;
[FieldOffset(4)]
public int top;
[FieldOffset(8)]
public int right;
[FieldOffset(12)]
public int bottom;
}
public static decimal MarshalAttributesOnPropertyAccessors
{
[return: MarshalAs(UnmanagedType.Currency)]
get
{
return 0m;
}
[param: MarshalAs(UnmanagedType.Currency)]
set
{
}
}
[DllImport("xyz.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool Method([MarshalAs(UnmanagedType.LPStr)] string input);
[DllImport("xyz.dll")]
private static extern void New1(int ElemCnt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] ar);
[DllImport("xyz.dll")]
private static extern void New2([MarshalAs(UnmanagedType.LPArray, SizeConst = 128)] int[] ar);
[DllImport("xyz.dll")]
private static extern void New3([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Bool, SizeConst = 64, SizeParamIndex = 1)] int[] ar);
public void CustomMarshal1([MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "MyCompany.MyMarshaler")] object o)
{
}
public void CustomMarshal2([MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "MyCompany.MyMarshaler", MarshalCookie = "Cookie")] object o)
{
}
}

6
ICSharpCode.Decompiler/Tests/TestRunner.cs

@ -73,6 +73,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -73,6 +73,12 @@ namespace ICSharpCode.Decompiler.Tests
TestFile(@"..\..\Tests\MultidimensionalArray.cs");
}
[Test]
public void PInvoke()
{
TestFile(@"..\..\Tests\PInvoke.cs");
}
[Test]
public void PropertiesAndEvents()
{

Loading…
Cancel
Save