2011-08-07 2 views
6

Je veux appeler via C#/PInvoke la fonction GetLogicalProcessorInformation, mais je suis coincé avec SYSTEM_LOGICAL_PROCESSOR_INFORMATION struct et struct CACHE_DESCRIPTOR.PInvoke pour GetLogicalProcessorInformation Fonction

Comment dois-je définir ces structures pour une utilisation correcte?

Principaux problèmes:
1. SYSTEM_LOGICAL_PROCESSOR_INFORMATION a union dans sa définition
2. SYSTEM_LOGICAL_PROCESSOR_INFORMATION a ULONGLONG dans sa définition
3. CACHE_DESCRIPTOR a WORD et DWORD dans sa définition.

Pouvez-vous m'aider avec ces structures?

+0

Pourquoi avez-vous downvote? – VMAtm

Répondre

10

Mise à jour: fixé le rassemblement de la structure qui doit être fait manuellement.

Il s'agit d'un P/invoke plutôt désordonné. Même lorsque vous avez défini les structures et l'union, il n'est pas trivial d'appeler la fonction car vous devez rassembler les structures manuellement.

[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 pour la réponse plus complète. – Dennis

+0

J'ai l'erreur de compilation suivante (sur .NET 1.1) 'Operator '+ =' ne peut pas être appliqué aux opérandes de type 'System.IntPtr' et 'int'. Puis-je utiliser le 'int *' au lieu de IntPtr? – VMAtm

+0

J'ai essayé d'utiliser ce qui suit: 'Item = new IntPtr (Item.ToInt32() + size);' et cela a fonctionné. Je vais dire, si je peux utiliser le 'int *'. – VMAtm

4

Un DWORD est uint et WORD est 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 est une structure avec une disposition Explicit et 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, 
} 

A ULONGLONG est un UInt64. Il s'agit d'aligner la structure sur une limite de 8 octets (24 octets). Comme David l'a souligné dans les commentaires, il est nécessaire et pour une raison quelconque, il manquait dans la bibliothèque Microsoft Interop.

Mise à jour: Ajout de structures manquantes et lien vers la bibliothèque Windows Interop à partir de Microsoft Research.

Source: WindowsInteropLib/Kernel32.cs

+1

Bien que cette réponse attire tous les upvotes, il me semble être sérieusement déficient de deux façons importantes. Ignorer le membre 'ULONGLONG [2] Reserved' signifie que la structure est de taille incorrecte, étant 20 octets plutôt que les 24 octets corrects. Et plus important encore, il n'y a aucune mention d'appeler réellement la fonction qui est plutôt difficile à obtenir correctement. –

+2

Merci de m'avoir fait remarquer David - je lisais juste ta réponse et je réalisais la même chose. – Dennis