gpt4 book ai didi

c# - 未正确对齐的字段

转载 作者:搜寻专家 更新时间:2023-10-31 02:02:21 25 4
gpt4 key购买 nike

我有以下 C++ 来使用 EnumDisplaySettings 获取有关特定监视器的信息WinAPI函数。

#include <iostream>
#include <Windows.h>

int main()
{
DEVMODE dm;
dm.dmSize = sizeof dm;

EnumDisplaySettings(L"\\\\.\\DISPLAY1", ENUM_CURRENT_SETTINGS, &dm);
std::wcout << "Name: " << dm.dmDeviceName << std::endl;
std::wcout << "Width: " << dm.dmPelsWidth << std::endl;
std::wcout << "Height: " << dm.dmPelsHeight << std::endl;
}

我正在尝试使用 EnumDisplaySettings C# 中的函数。

为此,我重新创建了 DEVMODEW作为 C# 结构并将其传递到方法中。

static void Main()
{
DeviceModeStruct deviceMode = new DeviceModeStruct();
deviceMode.dmSize = (ushort)Marshal.SizeOf(deviceMode);

bool successfullyGotScale = EnumDisplaySettings("\\\\.\\DISPLAY1",
ENUM_CURRENT_SETTINGS,
ref deviceMode);

if (successfullyGotScale)
{
Console.WriteLine($@"Name: {deviceMode.dmDeviceName}");
Console.WriteLine($@"Width: {deviceMode.dmPelsWidth}");
Console.WriteLine($@"Height: {deviceMode.dmPelsHeight}");
}
}

问题是,当我运行代码时,出现以下异常。

Unhandled Exception: System.TypeLoadException: Could not load type 'DeviceModeStruct'
from assembly 'DevModeSo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
because it contains an object field at offset 70 that is incorrectly aligned or
overlapped by a non-object field.
at DevModeSo.Program.Main()

据我所知,这个问题与

有关
[FieldOffset(70), MarshalAs(UnmanagedType.ByValTStr, SizeConst = STRING_SIZE)]
public string dmFormName;

this answer另一个类似的 Stack Overflow 问题似乎表明我可以拆分字符串来解决问题。

但是,当我尝试这样做以便代码使值与“DWORDS”对齐时,我遇到了同样的错误。

[FieldOffset(70)]
public char dmFormName1;

[FieldOffset(71)]
public char dmFormName2;

[FieldOffset(72), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)]
public string dmFormName3;

如何解决这个问题,同时仍然满足 DEVMODEW 定义的相同数据结构? ?


完整的 C# 代码

using System;
using System.Runtime.InteropServices;

namespace DevModeSo
{
class Program
{
private const int ENUM_CURRENT_SETTINGS = -1;

static void Main()
{
DeviceModeStruct deviceMode = new DeviceModeStruct();
deviceMode.dmSize = (ushort)Marshal.SizeOf(deviceMode);

bool successfullyGotScale = EnumDisplaySettings("\\\\.\\DISPLAY1",
ENUM_CURRENT_SETTINGS,
ref deviceMode);

if (successfullyGotScale)
{
Console.WriteLine($@"Name: {deviceMode.dmDeviceName}");
Console.WriteLine($@"Width: {deviceMode.dmPelsWidth}");
Console.WriteLine($@"Height: {deviceMode.dmPelsHeight}");
}
}

[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool EnumDisplaySettings(string deviceName,
int modeNum,
ref DeviceModeStruct deviceMode);

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Auto)]
struct DeviceModeStruct
{
private const int STRING_SIZE = 32;

[FieldOffset(0), MarshalAs(UnmanagedType.ByValTStr, SizeConst = STRING_SIZE)]
public string dmDeviceName;

[FieldOffset(32)] public ushort dmSpecVersion;

[FieldOffset(34)] public ushort dmDriverVersion;

[FieldOffset(36)] public ushort dmSize;

[FieldOffset(38)] public ushort dmDriverExtra;

[FieldOffset(40)] public uint dmFields;

[FieldOffset(44)] public PrinterOnlyFields printerMode;

[FieldOffset(44)] public DisplayOnlyFields displayMode;

[FieldOffset(60)] public short dmColor;

[FieldOffset(62)] public short dmDuplex;

[FieldOffset(64)] public short dmYResolution;

[FieldOffset(66)] public short dmTTOption;

[FieldOffset(68)] public short dmCollate;

[FieldOffset(70), MarshalAs(UnmanagedType.ByValTStr, SizeConst = STRING_SIZE)]
public string dmFormName;

[FieldOffset(102)] public ushort dmLogPixels;

[FieldOffset(104)] public uint dmBitsPerPel;

[FieldOffset(108)] public uint dmPelsWidth;

[FieldOffset(112)] public uint dmPelsHeight;

[FieldOffset(116)] public uint dmDisplayFlags;

[FieldOffset(116)] public uint dmNup;

[FieldOffset(120)] public uint dmDisplayFrequency;

[FieldOffset(124)] public uint dmICMMethod;

[FieldOffset(128)] public uint dmICMIntent;

[FieldOffset(132)] public uint dmMediaType;

[FieldOffset(136)] public uint dmDitherType;

[FieldOffset(140)] public uint dmReserved1;

[FieldOffset(144)] public uint dmReserved2;

[FieldOffset(148)] public uint dmPanningWidth;

[FieldOffset(152)] public uint dmPanningHeight;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct PrinterOnlyFields
{
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct Point
{
public int x;
public int y;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct DisplayOnlyFields
{
public Point dmPosition;
public uint dmDisplayOrientation;
public uint dmDisplayFixedOutput;
}
}
}

最佳答案

您应该删除所有 FieldOffset 属性并在 DeviceModeStruct 结构之外实现 union 。像这样:

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Auto)]
struct DeviceModeUnion
{
[FieldOffset(0)]
PrinterOnlyFields Printer;
[FieldOffset(0)]
Point Position;
[FieldOffset(0)]
DisplayOnlyFields Display;
}

....

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct DeviceModeStruct
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public ushort dmSpecVersion;
public ushort dmDriverVersion;
public ushort dmSize;
public ushort dmDriverExtra;
public uint dmFields;
public DeviceModeUnion union;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmFormName;
public ushort dmLogPixels;
public uint dmBitsPerPel;
public uint dmPelsWidth;
public uint dmPelsHeight;
public uint dmDisplayFlags;
public uint dmDisplayFrequency;
public uint dmICMMethod;
public uint dmICMIntent;
public uint dmMediaType;
public uint dmDitherType;
public uint dmReserved1;
public uint dmReserved2;
public uint dmPanningWidth;
public uint dmPanningHeight;
}

我没有根据 documentation 仔细检查 DeviceModeStruct ,但我相信你能做到。但是,与 C++ 头文件中定义的结构的大小相比,我可以确认此结构定义至少具有正确的大小。

关于c# - 未正确对齐的字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57360134/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com