簡體   English   中英

如何編組結構數組?

[英]How to marshall an array of structs?

using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        const int SystemPowerInformation = 11;
        const uint STATUS_SUCCESS = 0;

        [StructLayout(LayoutKind.Sequential)]
        struct PROCESSOR_POWER_INFORMATION
        {
            public uint  Number;
            public uint MaxMhz;
            public uint CurrentMhz;
            public uint MhzLimit;
            public uint MaxIdleState;
            public uint CurrentIdleState;
        }

        [DllImport("powrprof.dll")]
        static extern uint CallNtPowerInformation(
            int InformationLevel,
            IntPtr lpInputBuffer,
            int nInputBufferSize,
            [MarshalAs(UnmanagedType.LPArray)]
            out byte[]  lpOutputBuffer,
            int nOutputBufferSize
        );

        static void Main(string[] args)
        {


            byte[] buffer = new byte[4 * Marshal.SizeOf(typeof(PROCESSOR_POWER_INFORMATION))];
            uint retval = CallNtPowerInformation(
                SystemPowerInformation,
                IntPtr.Zero,
                0,
                out  buffer,
                4 * Marshal.SizeOf(typeof(PROCESSOR_POWER_INFORMATION))
            );

            if (retval == STATUS_SUCCESS)
                Console.WriteLine(buffer);
       }
    }
}

我正在嘗試從CallNtPowerInformation獲取一些數據。 我試圖創建一個結構並調用CallNtPowerInformationCallNtPowerInformation數據,但這沒有用。 因此,我試圖查看是否可以將數據放入字節數組,但是得到以下信息:

你調用的對象是空的。

我相信我正在將內存分配給緩沖區。

我不知道為什么。 任何指針都會有所幫助。

名為SystemPowerInformation的值為11常量名稱錯誤。 它應該命名為ProcessorInformation

您應該這樣聲明p / invoke:

[DllImport("powrprof.dll")]
static extern uint CallNtPowerInformation(
    int InformationLevel,
    IntPtr lpInputBuffer,
    int nInputBufferSize,
    [Out] PROCESSOR_POWER_INFORMATION[] processorPowerInformation,
    int nOutputBufferSize
);

為了調用該函數,您需要分配一個適當大小的PROCESSOR_POWER_INFORMATION結構數組。 像這樣:

PROCESSOR_POWER_INFORMATION[] powerInfo = 
    new PROCESSOR_POWER_INFORMATION[procCount];

CallNtPowerInformation的文檔告訴您使用GetSystemInfo可以算出您有多少個處理器。 您可以使用Environment.ProcessorCount

然后,您可以像下面這樣調用函數:

uint retval = CallNtPowerInformation(
    ProcessorInformation,
    IntPtr.Zero,
    0,
    powerInfo,
    powerInfo.Length*Marshal.SizeOf(typeof(PROCESSOR_POWER_INFORMATION))
);

這是一個完整的程序:

using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        const int ProcessorInformation = 11;
        const uint STATUS_SUCCESS = 0;

        [StructLayout(LayoutKind.Sequential)]
        struct PROCESSOR_POWER_INFORMATION
        {
            public uint Number;
            public uint MaxMhz;
            public uint CurrentMhz;
            public uint MhzLimit;
            public uint MaxIdleState;
            public uint CurrentIdleState;
        }

        [DllImport("powrprof.dll")]
        static extern uint CallNtPowerInformation(
            int InformationLevel,
            IntPtr lpInputBuffer,
            int nInputBufferSize,
            [Out] PROCESSOR_POWER_INFORMATION[] lpOutputBuffer,
            int nOutputBufferSize
        );

        static void Main(string[] args)
        {
            int procCount = Environment.ProcessorCount;
            PROCESSOR_POWER_INFORMATION[] procInfo =
                new PROCESSOR_POWER_INFORMATION[procCount]; 
            uint retval = CallNtPowerInformation(
                ProcessorInformation,
                IntPtr.Zero,
                0,
                procInfo,
                procInfo.Length * Marshal.SizeOf(typeof(PROCESSOR_POWER_INFORMATION))
            );
            if (retval == STATUS_SUCCESS)
            {
                foreach (var item in procInfo)
                {
                    Console.WriteLine(item.CurrentMhz);
                }
            }
        }
    }
}

將您的分段調用的參數類型更改為IntPtr:

[DllImport("powrprof.dll")]
    static extern uint CallNtPowerInformation(
        int InformationLevel,
        IntPtr lpInputBuffer,
        int nInputBufferSize,
        IntPtr lpOutputBuffer,
        int nOutputBufferSize
    );

並在調用它之前使用它:

GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
IntPtr ptr = handle.AddrOfPinnedObject();

然后通過傳遞IntPtr作為參數來調用它。

使用后不要忘記釋放!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM