mercredi 22 juillet 2015

Reflection in combination with marshal not working

I have a problem with reflection in combination with MarshalAs attributes. I would like to dynamically create structs with reflection durng runtime. The structs may contain arrays which need to me marshaled. The Field.SetMarshal() Method is obsoletze since .NET 2.0 and I'm failing to find an alternative.

Example of struct which im building during runtime:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] 
public struct Example
{
    public int   var1;
    public float var2;
    public byte  var3;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public int[] var4;
}

Code using reflection to build structs:

TypeBuilder tb = mb.DefineType(pT.name,                          // Name of struct type
                                TypeAttributes.Public |           // Public scope
                                TypeAttributes.SequentialLayout | // Sequential layout
                                TypeAttributes.AnsiClass,         // Ansi Charset
                                typeof(ValueType),                // Value type
                                PackingSize.Size1);               // Packing size is 1 byte

// Add public fields to new struct type
foreach (parsedField pF in pT.fields)
{
    FieldBuilder fb = tb.DefineField(pF.name, pF.type, FieldAttributes.Public);

    // Add Marshall information to arrays
    if (fb.FieldType.IsArray)
    {
        // ADD MARSHAL INFORMATION HERE
    }
}

In the documentation of the obsolete UnmanagedMarshal class Microsoft says: "Emit the MarshalAs custom attribute instead"

Well I tried to make an CustomAttribute ("MarshalAs") and added it with Field.SetCustomAttribute() but this does not work either - the size of the struct is alyways wrong.

    [AttributeUsage(AttributeTargets.Field)]
    public class MarshalAs : System.Attribute
    {
        public UnmanagedType type;
        public int SizeConst;

        public MarshalAs(UnmanagedType type, int SizeConst)
        {
            this.type = type;
            this.SizeConst = SizeConst;
        }
    }

...

TypeBuilder tb = mb.DefineType(pT.name,                          // Name of struct type
                                TypeAttributes.Public |           // Public scope
                                TypeAttributes.SequentialLayout | // Sequential layout
                                TypeAttributes.AnsiClass,         // Ansi Charset
                                typeof(ValueType),                // Value type
                                PackingSize.Size1);               // Packing size is 1 byte

// Add public fields to new struct type
foreach (parsedField pF in pT.fields)
{
    FieldBuilder fb = tb.DefineField(pF.name, pF.type, FieldAttributes.Public);

    // Add Marshall information to arrays
    if (fb.FieldType.IsArray)
    {
        ConstructorInfo ci = typeof(MarshalAs).GetConstructor(new Type[] { typeof(UnmanagedType), typeof(int) });

        CustomAttributeBuilder customBuilder = new CustomAttributeBuilder(ci, new object[] { UnmanagedType.ByValArray, 8 });

        fb.SetCustomAttribute(customBuilder);
    }
}

Does anyone have an idea what I can do?

best regards





Aucun commentaire:

Enregistrer un commentaire