Here is the latest piece of code I wish to share with everyone since I run into this myself, I am sure others will be interested also.
The C++ Part
Firstly you will need to create a new DLL project in Visual Studio. You will also need to add this line into the cpp file for your project:
[cc lang=”c++”]#include [/cc]
This will allow you to access the intrinsic __cpuid call.
Next, I use a custom structure to hold the data returned by the function call. I do this mainly for readability since it helps when referencing. The code for the structure is as follows and should be added to the header file.
[cc lang=”c++”]struct CPUInfo
{
int EAX;
int EBX;
int ECX;
int EDX;
};[/cc]
Simple enough eh? Good. Now we need to construct a function call that will wrap the results from a __cpuid call into the structure above. Again, this is quite simple:
[cc lang=”c++”]extern “C” __declspec(dllexport) CPUInfo cpuID(int infoType)
{
CPUInfo i;
int results[4] = { 0, 0, 0, 0 };
__try
{
__cpuid(results, infoType);
}
__except (EXCEPTION_EXECUTE_HANDLER) {}
i.EAX = results[0];
i.EBX = results[1];
i.ECX = results[2];
i.EDX = results[3];
return i;
}[/cc]
Finally you will need the following function definition for the header file:
[cc lang=”c++”]extern “C” __declspec(dllexport) CPUInfo cpuID(int infoType);[/cc]
As you can see. The above function also checks for any exceptions – it needs this as some older CPUs do not support the cpuid call. In these cases it will simply return a CPUInfo structure filled with 0’s so that the code doesn’t break anything.
Now. You will need to compile the DLL and then you can use it in your C# project using the following method.
The C# Part
First. Create an analogue of the C++ CPUInfo class in C#. This is really simple to do and the following is what is needed, for those who do not wish to try themselves:
[cc lang=”c#”][StructLayout(LayoutKind.Sequential)]
struct CPUInfo
{
public int EAX;
public int EBX;
public int ECX;
public int EDX;
}[/cc]
Finally you will need the pinvoke definition. Depending on the name of the DLL (I called mine HardwareInfo.dll) the following code will be slightly different:
[cc lang=”c#”]///
/// This pinvoke method will return the result from a __cpuid call, if supported.
///
/// A code that indicates what information this instruction retrieves.
/// A CPUInfo structure giving the result from the query, or an empty structure if not supported.
[DllImport(“HardwareInfo.dll”, CallingConvention = CallingConvention.Cdecl)]
public static extern CPUInfo _cpuid(uint infoType);[/cc]
Hopefully that wasn’t too bad. Here is an example of how you would use the above code:
[cc lang=”c#”]CPUInfo example = cpuID(0x00000000);
uint maxSupportedStandardLevels = (uint)(example.EAX & 0xffff);[/cc]
The above code will tell you the maximum supported level of call that is supported on the current processor.
Notes:
Just remember that you will need to add a reference to the System.Runtime.InteropServices namespace if you are going to use this code.
As always, comments, improvements and suggestions are welcome.