无法将类型封送为非托管结构

时间:2018-12-20 10:30:10

标签: c# winapi struct pinvoke marshalling

我正在尝试更改核心项目中的分辨率。

var devmode = default(Devmode);
devmode.DmDeviceName = new string(new char[32]);
devmode.DmFormName = new string(new char[32]);
devmode.Dmsize = (short)Marshal.SizeOf(devmode);

在上述代码的第三行,它失败并产生“无法封送为非托管结构;无法计算出有意义的大小或偏移量”错误。

任何人都可以提供一些有关我应该如何解决此问题的见解吗?奇怪的是,在我提取了其他本不应该影响该代码的代码之前,它运行良好。

结构:

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Devmode
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public string DmFormName;
    public string DmDeviceName;

    public short Dmsize;

    public int DmPelsWidth;
    public int DmPelsHeight;

    private readonly short dmlogPixels;
    private readonly short dmbitsPerPel;
    private readonly int dmdisplayFlags;
    private readonly int dmdisplayFrequency;
    private readonly int dmiCMMethod;
    private readonly int dmiCMIntent;
    private readonly int dmmediaType;
    private readonly int dmditherType;
    private readonly int dmreserved1;
    private readonly int dmreserved2;
    private readonly int dmpanningWidth;
    private readonly int dmpanningHeight;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    private readonly short dmspecVersion;
    private readonly short dmdriverVersion;
    private readonly short dmdriverExtra;
    private readonly int dmfields;
    private readonly int dmpositionX;
    private readonly int dmpositionY;
    private readonly int dmdisplayOrientation;
    private readonly int dmdisplayFixedOutput;
    private readonly short dmcolor;
    private readonly short dmduplex;
    private readonly short dmyResolution;
    private readonly short dmtTOption;
    private readonly short dmcollate;
}

编辑:我现在将代码更改为此:

        [StructLayout(LayoutKind.Sequential)]
    public struct Devmode
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]

        private readonly string dmdeviceName;

        private readonly short dmspecVersion;
        private readonly short dmdriverVersion;

        public short Dmsize;

        private readonly short dmdriverExtra;
        private readonly int dmfields;
        private readonly int dmpositionX;
        private readonly int dmpositionY;
        private readonly int dmdisplayOrientation;
        private readonly int dmdisplayFixedOutput;
        private readonly short dmcolor;
        private readonly short dmduplex;
        private readonly short dmyResolution;
        private readonly short dmtTOption;
        private readonly short dmcollate;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
        private readonly string dmformName;
        private readonly short dmlogPixels;
        private readonly short dmbitsPerPel;

        public int dmpelsWidth;
        public int dmpelsHeight;

        private readonly int dmdisplayFlags;
        private readonly int dmdisplayFrequency;
        private readonly int dmiCMMethod;
        private readonly int dmiCMIntent;
        private readonly int dmmediaType;
        private readonly int dmditherType;
        private readonly int dmreserved1;
        private readonly int dmreserved2;
        private readonly int dmpanningWidth;
        private readonly int dmpanningHeight;
    }

但是,dmpelsWidth,dmpelsHeight和Dmsize出现错误。 “公共”成员必须先于“私人”成员...

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

DmDeviceName字段缺少MarshalAs属性。

它应该像这样:

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DmFormName;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DmDeviceName;

顺便说一句,这段代码毫无意义:

devmode.DmDeviceName = new string(new char[32]);
devmode.DmFormName = new string(new char[32]);

只需删除这些行。这些值将由调用的WinAPI函数填充(如果可能)。

最大的问题是:您的结构体定义无效!现场订单很重要!您不允许对字段进行重新排序。请使用结构定义作为我posted in this answer