I'm writing a GPU tool with C# for the UI and command line .exes that the user interacts with, and writing the necessary driver code to make it work in C++ (via .dll). So far, loading an unmanaged .dll file written in C++ is trivial and easy, but there's one part that confuses me (mostly because I am not a C# expert, yet). How do you handle structures as parameters? My code crashes when I try to use a structure as a parameter. Should I use an IntPtr instead and just cast it?
I'll show you a bit of code to show you what I mean:
C++:
typedef struct _GPUDETAILS
{
CHAR DeviceDesc[128];
DWORD DeviceID;
DWORD VendorID;
} GPUDETAILS;
...
GPUMONEXDRIVERNVAPI_API int Drv_GetGpuDetails( int AdapterNumber, GPUDETAILS* pGpuDetails )
{
_LOG( __FUNCTION__ << "(): TODO: Implement...\n" );
if( !pGpuDetails )
{
_ERROR( "Invalid parameter!" << std::endl );
return 0;
}
_LOG( __FUNCTION__ << "(): Gathering GPU details...\n" );
strcpy( pGpuDetails->DeviceDesc, "NVIDIA Something..." );
pGpuDetails->DeviceID = 0xFFFF; /* TODO */
pGpuDetails->VendorID = 0x10DE; /* This is always a given */
return 1;
}
Something simple for now. Let's move on to the C# part...
namespace GPUMonEx
{
/*
* GPU Details structure
* NOTE: Subject to change
*/
public struct GPUDETAILS
{
public string DeviceDesc;
public UInt32 DeviceID;
public UInt32 VendorID;
}
/*
* Driver importer classes for the following APIs under Windows
* TODO: Get ahold of Intel's SDK as well as implement AMD's equivalent for their hardware.
*
* NVAPI - NVIDIA Driver Specific functionality
* D3DKMT - Direct3D internal driver functions. Should work for all GPUs, but currently needed for Intel.
*/
static class DrvD3DKMT
{
[DllImport("GPUMonEx.Driver.D3DKMT.dll")]
public static extern int Drv_Initialize();
[DllImport("GPUMonEx.Driver.D3DKMT.dll")]
public static extern void Drv_Uninitialize();
[DllImport("GPUMonEx.Driver.D3DKMT.dll")]
public static extern unsafe int Drv_GetGpuDetails(int Adapter, ref GPUDETAILS pGpuDetails);
[DllImport("GPUMonEx.Driver.D3DKMT.dll")]
public static extern int Drv_GetOverallGpuLoad();
[DllImport("GPUMonEx.Driver.D3DKMT.dll")]
public static extern int Drv_GetGpuTemperature();
}
static class DrvNVAPI
{
[DllImport("GPUMonEx.Driver.NVAPI.dll")]
public static extern int Drv_Initialize();
[DllImport("GPUMonEx.Driver.NVAPI.dll")]
public static extern void Drv_Uninitialize();
[DllImport("GPUMonEx.Driver.NVAPI.dll")]
public static extern unsafe int Drv_GetGpuDetails(int Adapter, ref GPUDETAILS pGpuDetails);
[DllImport("GPUMonEx.Driver.NVAPI.dll")]
public static extern int Drv_GetOverallGpuLoad();
[DllImport("GPUMonEx.Driver.NVAPI.dll")]
public static extern int Drv_GetGpuTemperature();
}
/*
* GPU Driver interfacing classes (the ones you actually call in user mode)
*/
public abstract class GPUDriverBase
{
public abstract int Initialize();
public abstract void Uninitialize();
public abstract int GetGpuDetails( int Adapter, ref GPUDETAILS pGpuDetails );
public abstract int GetOverallGpuLoad();
public abstract int GetGpuTemperature();
}
public class GPUDriverD3DKMT : GPUDriverBase
{
public override int Initialize()
{
return DrvD3DKMT.Drv_Initialize();
}
public override void Uninitialize()
{
DrvD3DKMT.Drv_Uninitialize();
}
public override int GetGpuDetails( int Adapter, ref GPUDETAILS pGpuDetails )
{
return DrvD3DKMT.Drv_GetGpuDetails( Adapter, ref pGpuDetails );
}
public override int GetOverallGpuLoad()
{
return DrvD3DKMT.Drv_GetOverallGpuLoad();
}
public override int GetGpuTemperature()
{
return DrvD3DKMT.Drv_GetGpuTemperature();
}
}
public class GPUDriverNVAPI : GPUDriverBase
{
public override int Initialize()
{
return DrvNVAPI.Drv_Initialize();
}
public override void Uninitialize()
{
DrvNVAPI.Drv_Uninitialize();
}
public override int GetGpuDetails(int Adapter, ref GPUDETAILS pGpuDetails)
{
return DrvNVAPI.Drv_GetGpuDetails(Adapter, ref pGpuDetails);
}
public override int GetOverallGpuLoad()
{
return DrvNVAPI.Drv_GetOverallGpuLoad();
}
public override int GetGpuTemperature()
{
return DrvNVAPI.Drv_GetGpuTemperature();
}
}
}
So, focusing on Drv_GetGpuDetails(), how do I actually get a valid structure filled in here? Calling that function just crashes. I'm sure it's a stupid easy fix, but once again, I'm far too C++ oriented and have yet to get used to C# in the same manner.
Any advice is welcome (on the question at hand or anything else).
Shogun
↧