2011-08-07 12 views
6

Quiero llamar a través de C#/PInvocar la función GetLogicalProcessorInformation, pero estoy atascado con SYSTEM_LOGICAL_PROCESSOR_INFORMATION struct y CACHE_DESCRIPTOR struct.PInvoke para GetLogicalProcessorInformation Función

¿Cómo debo definir estas estructuras para un uso correcto?

problemas principales: 1.
SYSTEM_LOGICAL_PROCESSOR_INFORMATION tiene sindicato en su definición
2. SYSTEM_LOGICAL_PROCESSOR_INFORMATION tiene ULONGLONG en su definición
3. CACHE_DESCRIPTOR tiene WORD y DWORD en su definición.

¿Me pueden ayudar con estas estructuras?

+0

¿Alguna de las razones del downvote? – VMAtm

Respuesta

10

Actualizado: fija la estructura de clasificación que tiene que hacer manualmente.

Esto es bastante complicado P/invoke. Incluso cuando tiene las estructuras y la unión definidas, no es trivial llamar a la función porque debe ordenar las estructuras manualmente.

[StructLayout(LayoutKind.Sequential)] 
public struct PROCESSORCORE 
{ 
    public byte Flags; 
}; 

[StructLayout(LayoutKind.Sequential)] 
public struct NUMANODE 
{ 
    public uint NodeNumber; 
} 

public enum PROCESSOR_CACHE_TYPE 
{ 
    CacheUnified, 
    CacheInstruction, 
    CacheData, 
    CacheTrace 
} 

[StructLayout(LayoutKind.Sequential)] 
public struct CACHE_DESCRIPTOR 
{ 
    public byte Level; 
    public byte Associativity; 
    public ushort LineSize; 
    public uint Size; 
    public PROCESSOR_CACHE_TYPE Type; 
} 

[StructLayout(LayoutKind.Explicit)] 
public struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION_UNION 
{ 
    [FieldOffset(0)] 
    public PROCESSORCORE ProcessorCore; 
    [FieldOffset(0)] 
    public NUMANODE NumaNode; 
    [FieldOffset(0)] 
    public CACHE_DESCRIPTOR Cache; 
    [FieldOffset(0)] 
    private UInt64 Reserved1; 
    [FieldOffset(8)] 
    private UInt64 Reserved2; 
} 

public enum LOGICAL_PROCESSOR_RELATIONSHIP 
{ 
    RelationProcessorCore, 
    RelationNumaNode, 
    RelationCache, 
    RelationProcessorPackage, 
    RelationGroup, 
    RelationAll = 0xffff 
} 

public struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION 
{ 
    public UIntPtr ProcessorMask; 
    public LOGICAL_PROCESSOR_RELATIONSHIP Relationship; 
    public SYSTEM_LOGICAL_PROCESSOR_INFORMATION_UNION ProcessorInformation; 
} 

[DllImport(@"kernel32.dll", SetLastError=true)] 
public static extern bool GetLogicalProcessorInformation(
    IntPtr Buffer, 
    ref uint ReturnLength 
); 

private const int ERROR_INSUFFICIENT_BUFFER = 122; 

public static SYSTEM_LOGICAL_PROCESSOR_INFORMATION[] MyGetLogicalProcessorInformation() 
{ 
    uint ReturnLength = 0; 
    GetLogicalProcessorInformation(IntPtr.Zero, ref ReturnLength); 
    if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER) 
    { 
     IntPtr Ptr = Marshal.AllocHGlobal((int)ReturnLength); 
     try 
     { 
      if (GetLogicalProcessorInformation(Ptr, ref ReturnLength)) 
      { 
       int size = Marshal.SizeOf(typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); 
       int len = (int)ReturnLength/size; 
       SYSTEM_LOGICAL_PROCESSOR_INFORMATION[] Buffer = new SYSTEM_LOGICAL_PROCESSOR_INFORMATION[len]; 
       IntPtr Item = Ptr; 
       for (int i = 0; i < len; i++) 
       { 
        Buffer[i] = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION)Marshal.PtrToStructure(Item, typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); 
        Item += size; 
       } 
       return Buffer; 
      } 
     } 
     finally 
     { 
      Marshal.FreeHGlobal(Ptr); 
     } 
    } 
    return null; 
} 

static void Main(string[] args) 
{ 
    SYSTEM_LOGICAL_PROCESSOR_INFORMATION[] Buffer = MyGetLogicalProcessorInformation(); 
    for (int i=0; i<Buffer.Length; i++) 
    { 
     Console.WriteLine(Buffer[i].ProcessorMask); 
    } 
} 
+1

+1 para la respuesta más completa. – Dennis

+0

Tengo el siguiente error de compilación (en .NET 1.1) 'Operator '+ =' no se puede aplicar a operandos de tipo 'System.IntPtr' e 'int''. ¿Puedo usar 'int *' en lugar de IntPtr? – VMAtm

+0

Intenté utilizar lo siguiente: 'Item = new IntPtr (Item.ToInt32() + size);' y funcionó. Te diré, si puedo usar el 'int *'. – VMAtm

4

A DWORD es un uint y WORD es un ushort.

[StructLayout(LayoutKind.Sequential)] 
struct CACHE_DESCRIPTOR 
{ 
    public byte Level; 
    public byte Associativity; 
    public ushort LineSize; 
    public uint Size; 
    public PROCESSOR_CACHE_TYPE Type; 
} 

enum PROCESSOR_CACHE_TYPE 
{ 
    Unified = 0, 
    Instruction = 1, 
    Data = 2, 
    Trace = 3, 
} 

A union es una estructura con un diseño de Explicit y FieldOffset.

[StructLayout(LayoutKind.Sequential)] 
struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION 
{ 
    public UIntPtr ProcessorMask; 
    public LOGICAL_PROCESSOR_RELATIONSHIP Relationship; 
    public ProcessorRelationUnion RelationUnion; 
} 

[StructLayout(LayoutKind.Explicit)] 
struct ProcessorRelationUnion 
{ 
    [FieldOffset(0)] public CACHE_DESCRIPTOR Cache; 
    [FieldOffset(0)] public uint NumaNodeNumber; 
    [FieldOffset(0)] public byte ProcessorCoreFlags; 
    [FieldOffset(0)] private UInt64 Reserved1; 
    [FieldOffset(8)] private UInt64 Reserved2; 
} 

[StructLayout(LayoutKind.Sequential)] 
struct CACHE_DESCRIPTOR 
{ 
    public byte Level; 
    public byte Associativity; 
    public ushort LineSize; 
    public uint Size; 
    public PROCESSOR_CACHE_TYPE Type; 
} 

enum LOGICAL_PROCESSOR_RELATIONSHIP : uint 
{ 
    ProcessorCore = 0, 
    NumaNode = 1, 
    RelationCache = 2, 
} 

Un ULONGLONG es una UInt64. Se trata de alinear la estructura con un límite de 8 bytes (24 bytes). Como David señaló en los comentarios, es necesario y por alguna razón faltaba en la biblioteca Microsoft Interop.

Actualización: Se han agregado las estructuras faltantes y se ha vinculado a la biblioteca de Windows Interop de Microsoft Research.

Fuente: WindowsInteropLib/Kernel32.cs

+1

Aunque esta respuesta atrae a todos los votos a favor, me parece seriamente deficiente en dos aspectos importantes. Ignorar el miembro 'ULONGLONG [2] Reserved' significa que la estructura tiene un tamaño incorrecto, con 20 bytes en lugar de los 24 bytes correctos. Y más importante aún, no hay mención de llamar realmente a la función, que es bastante complicada para hacerlo bien. –

+2

Gracias por señalar eso David - Estaba leyendo tu respuesta y me di cuenta de lo mismo. – Dennis

Cuestiones relacionadas