none
Reflection und Marshaling RRS feed

  • Frage

  • Hallo,

    ich möchte zur Laufzeit ein struct erzeugen, wobei die Arrays des structs das MarshalAs Attribute aufweisen müssen:

    Beispiel für ein zur Laufzeit erzeugtes struct:

        

    [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;
    }

    Das Erzeugen des structs scheint weitestgehend zu funktionieren jedoch weiß ich nicht wie ich die Marshaling Information des Arrays erzeugen soll (zumal die FieldBuilder.SetMarshal() Funktion veraltet ist).

    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)
            {
            	MarshalAsAttribute maa = new MarshalAsAttribute(UnmanagedType.ByValArray);
                    maa.SizeConst = pF.arrSize;
    
    		// ADD MARSHALING INFO HERE
    	        //fb.SetMarshal(?????);
            }
    }

    besten Dank!


    • Bearbeitet ReflectionDude Mittwoch, 22. Juli 2015 08:59 Formatierung
    Mittwoch, 22. Juli 2015 08:53

Antworten

  • Hallo,

    vielen Dank für deine Antwort. Ich habe es nun folgendermaßen gelöst:

    FieldBuilder fb = tb.DefineField(pF.name, pF.type, FieldAttributes.Public);
    
    // Add Marshall information to arrays
    // The "MarshallAs" attribute has to be passed with a CustomAttributeBuilder 
    if (fb.FieldType.IsArray)
    {
        // First we define a list of types of the arguments of the "MarshalAs" attribute constructor
        Type[] argTypes = new Type[] { typeof(UnmanagedType) };
    
        // Now we create a list of concrete constructor arguments for the "MarshalAs" attribute constructor
        object[] args = new object[] { UnmanagedType.ByValArray };
    
        // We need the field information of "SizeConst" of the MarshalAs attribute 
        FieldInfo[] sizeConstField = new FieldInfo[] { typeof(MarshalAsAttribute).GetField("SizeConst") };
    
        // We create the value for the field "SizeConst"
        object[] sizeConstValue = new object[] { pF.arrSize };
    
        // Now we retrieve the constructor of "MarshalAs" attribute that matches specified constructor argument types
        ConstructorInfo ci = typeof(MarshalAsAttribute).GetConstructor(argTypes);
    
        // Create builder for "MarshalAs" attribute
        CustomAttributeBuilder customBuilder = new CustomAttributeBuilder(ci, args, sizeConstField, sizeConstValue);
    
        // Set builder for MarshalAs attribute                              
        fb.SetCustomAttribute(customBuilder);
    }

    Mittwoch, 22. Juli 2015 12:47

Alle Antworten

  • Hallo ReflectionDude,

    versuch doch mal Folgendes:

    // 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)
            {
            	MarshalAsAttribute maa = new MarshalAsAttribute(UnmanagedType.ByValArray);
                    maa.SizeConst = pF.arrSize;
    
                var attributeParams = new[] { typeof(UnmanagedType) };
                var classCtorInfo = typeof(MarshalAsAttribute).GetConstructor(attributeParams);
                var attributeBuilder = new CustomAttributeBuilder(classCtorInfo, new object[] { UnmanagedType.ByValArray });
    
                fb.SetCustomAttribute(attributeBuilder);
            }
    }


    Mittwoch, 22. Juli 2015 12:40
  • Hallo,

    vielen Dank für deine Antwort. Ich habe es nun folgendermaßen gelöst:

    FieldBuilder fb = tb.DefineField(pF.name, pF.type, FieldAttributes.Public);
    
    // Add Marshall information to arrays
    // The "MarshallAs" attribute has to be passed with a CustomAttributeBuilder 
    if (fb.FieldType.IsArray)
    {
        // First we define a list of types of the arguments of the "MarshalAs" attribute constructor
        Type[] argTypes = new Type[] { typeof(UnmanagedType) };
    
        // Now we create a list of concrete constructor arguments for the "MarshalAs" attribute constructor
        object[] args = new object[] { UnmanagedType.ByValArray };
    
        // We need the field information of "SizeConst" of the MarshalAs attribute 
        FieldInfo[] sizeConstField = new FieldInfo[] { typeof(MarshalAsAttribute).GetField("SizeConst") };
    
        // We create the value for the field "SizeConst"
        object[] sizeConstValue = new object[] { pF.arrSize };
    
        // Now we retrieve the constructor of "MarshalAs" attribute that matches specified constructor argument types
        ConstructorInfo ci = typeof(MarshalAsAttribute).GetConstructor(argTypes);
    
        // Create builder for "MarshalAs" attribute
        CustomAttributeBuilder customBuilder = new CustomAttributeBuilder(ci, args, sizeConstField, sizeConstValue);
    
        // Set builder for MarshalAs attribute                              
        fb.SetCustomAttribute(customBuilder);
    }

    Mittwoch, 22. Juli 2015 12:47
  • Freut mich, dass es jetzt funktioniert. Am besten markierst du deinen Beitrag noch als Antwort, damit es für andere einfacher ist, wenn die ein ähnliches Problem haben.
    Mittwoch, 22. Juli 2015 14:32