With some inspiration from the OpenHardwareMonitor Project i have made myself a nice gadget to monitor CPU and GPU metrics Temperature, Load, etc.
It works fine but I am running in to a
[DllImport("nvapi.dll", CallingConvention = CallingConvention.Cdecl, PreserveSig = true)]
private static extern IntPtr nvapi_QueryInterface(uint id);
private delegate NvStatus NvAPI_EnumPhysicalGPUsDelegate([Out] NvPhysicalGpuHandle gpuHandles, out int gpuCount);
private static readonly NvAPI_EnumPhysicalGPUsDelegate NvAPI_EnumPhysicalGPUs;
NvAPI_EnumPhysicalGPUs = Marshal.GetDelegateForFunctionPointer(nvapi_QueryInterface(0xE5AC921F), typeof(NvAPI_EnumPhysicalGPUsDelegate)) as NvAPI_EnumPhysicalGPUsDelegate;
status = NvAPI_EnumPhysicalGPUs != null ? NvAPI_EnumPhysicalGPUs(PhysicalGPUHandles, out PhysicalGPUHandlesCount) : NvStatus.FUNCTION_NOT_FOUND; // warning is thrown here
First, the functions are C-style, not C++. Which is fortunate, since interoping with C++ directly from C# is a huge pain (you'd really want to use C++/CLI in that case).
Native interop is not easy. You need to understand who owns what memory, how to allocate and deallocate it, and you need to pay a lot of attention to whether you're running 32-bit or 64-bit.
At first glance, you're missing a calling convention on the delegate, so it will default to
StdCall. However, as defined in NVAPI (and as very reasonable for interop libraries), you are supposed to use
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate NvStatus NvAPI_EnumPhysicalGPUsDelegate([Out] NvPhysicalGpuHandle gpuHandles, out int gpuCount);
The tricky thing with Cdecl and StdCall is that both are very similar (the arguments are passed on stack right-to-left, the return value goes in EAX if integer or poitner etc.), except that in Cdecl, the caller is responsible for clearing the stack, while in StdCall, it's the callee's job. This means that P/Invoking with StdCall instead of Cdecl will almost always work (the .NET runtime notices the stack imbalance and fixes it), but will produce a warning.
If this doesn't solve your problem, pay attention to the bitness. Try using the 32-bit library from a 32-bit .NET application.