[英]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
獲取一些數據。 我試圖創建一個結構並調用CallNtPowerInformation
並CallNtPowerInformation
數據,但這沒有用。 因此,我試圖查看是否可以將數據放入字節數組,但是得到以下信息:
你調用的對象是空的。
我相信我正在將內存分配給緩沖區。
我不知道為什么。 任何指針都會有所幫助。
名為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.