Implementación de estructura C++ a C#

Iniciado por Eleкtro, 13 Diciembre 2015, 17:50 PM

0 Miembros y 1 Visitante están viendo este tema.

Eleкtro

Hola

Publico el tema aquí, por que creo que me podrá servir de más ayuda.

Estoy tratando de implementar la estructura DEVMODE en C#:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd183565%28v=vs.85%29.aspx
( y no me sirven las implementaciones de pinvoke.net u otros ejemplos online, ya que todas las que he visto hasta ahora son erroneas o desactualizadas en algún sentido )



He estado comparando los offsets en C++ y C#, en C++ con la macro offsetof y en C# con la función Marshal.OffsetOf, hasta llegar al miembro dmFields todo es correcto;
el problema que tengo, es que el offset del miembro dmColor es 60 en C++, mientras que en mi implementación es 68, esto quiere decir que mi implementación de los miembros de la primera union es incorrecta.

Según un experto en código no administrado, mi representación de las unions y el enfoque que le stoy dando es correcto, pero no debe ser del todo así, ya que las posiciones/offsets son distintas.

Código (csharp) [Seleccionar]
   [StructLayout(LayoutKind.Sequential)]
   public struct DevMode {
    private const int CchDeviceName = 32;
    private const int CchFormName = 32;
   
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CchDeviceName)]
    public string DeviceName;
    public short SpecVersion;
    public short DriverVersion;
    public short Size;
    public short DriverExtra;
    public DeviceModeFields Fields;
    public UnionDevMode1 test1;
    public short Color;
    public short Duplex;
    public short YResolution;
    public short TTOption;
    public short Collate;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CchFormName)]
    public string FormName;
    public short LogPixels;
    public int BitsPerPixel;
    public int PixelsWidth;
    public int PixelsHeight;
    public UnionDevMode2 test2;
    public int DisplayFrequency;
    public int IcmMethod;
    public int IcmIntent;
    public int MediaType;
    public int DitherType;
    public int Reserved1;
    public int Reserved2;
    public int PanningWidth;
    public int PanningHeight;
   }
   
   [StructLayout(LayoutKind.Explicit)]
   public struct UnionDevMode1 {
    [FieldOffset(0)] public SubUnionDevMode1 subUnion1;
    [FieldOffset(0)] public SubUnionDevMode2 subUnion2;
   }
   
   [StructLayout(LayoutKind.Sequential)]
   public struct SubUnionDevMode1 {
    public short Orientation;
    public short PaperSize;
    public short PaperLength;
    public short PaperWidth;
    public short Scale;
    public short Copies;
    public short DefaultSource;
    public short PrintQuality;
   }
   
   [StructLayout(LayoutKind.Sequential)]
   public struct SubUnionDevMode2 {
    public Win32.Types.Point Position;
    public DeviceModeDisplayOrientation DisplayOrientation;
    public int DisplayFixedOutput;
   }
   
   [StructLayout(LayoutKind.Explicit)]
   public struct UnionDevMode2 {
   
    [FieldOffset(0)] public int DisplayFlags;
    [FieldOffset(0)] public int Nup;
   
   }


El problema está en el miembro UnionDevMode1 , o al menos todo me indica eso, mejor dicho en alguno de los miembros de la estructura  SubUnionDevMode1 o  SubUnionDevMode2 , sin embargo, me he asegurado de que los types ocupan el mismo tamaño que en C++, vease:

POINTL = 8 bytes.
Win32.Types.Point = 8 bytes.

DeviceModeFields = int (4 bytes)
DeviceModeDisplayOrientation = int (4 bytes)

Teniendo esto en cuenta, ¿alguien es capaz de ver en lo que estoy fallando?.








ivancea96

¿Podría ser cosa del tamaño de 'DeviceModeFields'? ¿Tiene el tamaño correcto? O los miembros del union tienen el mismo offset en ambas implementaciones?

Eleкtro

Cita de: ivancea96 en 13 Diciembre 2015, 18:14 PM
¿Podría ser cosa del tamaño de 'DeviceModeFields'? ¿Tiene el tamaño correcto?

Gracias ivancea. Si, lo añadi a mi post mientras escribias, es un tipo Int32 en .Net (4 bytes)

Cita de: ivancea96 en 13 Diciembre 2015, 18:14 PM
los miembros del union tienen el mismo offset en ambas implementaciones?

Lo he vuelto a revisar y resulta que no. Ha sido todo un despiste muy tonto, el código que puse era en C# pero solo lo puse por conveniencia ya que es un lenguaje más común, en realidad lo estoy tratando en Vb.Net y a diferencia del código de C# se me olvidó declarar los miembros de la estructura UnionDevMode1 de forma explícita, era secuencial así que SubUnionDevMode2 estaba en el offset 16 y no en el 0 donde debía estar.

Solucionado

saludos