C# Programming/The .NET Framework/Marshalling
Appearance
The .NET Framework currently supports calling unmanaged functions and using unmanaged data, a process called marshalling. This is often done to use Windows API functions and data structures, but can also be used with custom libraries.
GetSystemTimes
[edit | edit source]A simple example to start with is the Windows API function GetSystemTimes
. It is declared as:
BOOL WINAPI GetSystemTimes(
__out_opt LPFILETIME lpIdleTime,
__out_opt LPFILETIME lpKernelTime,
__out_opt LPFILETIME lpUserTime
);
LPFILETIME
is a pointer to a FILETIME
structure, which is simply a 64-bit integer. Since C# supports 64-bit numbers through the long type, we can use that. We can then import and use the function as follows:
using System;
using System.Runtime.InteropServices;
public class Program
{
[DllImport("kernel32.dll")]
static extern bool GetSystemTimes(out long idleTime, out long kernelTime, out long userTime);
public static void Main()
{
long idleTime, kernelTime, userTime;
GetSystemTimes(out idleTime, out kernelTime, out userTime);
Console.WriteLine("Your CPU(s) have been idle for: " + (new TimeSpan(idleTime)).ToString());
Console.ReadKey();
}
}
Note that the use of out or ref in parameters automatically makes it a pointer to the unmanaged function.
GetProcessIoCounters
[edit | edit source]To pass pointers to structs, we can use the out or ref keyword:
using System;
using System.Runtime.InteropServices;
public class Program
{
struct IO_COUNTERS
{
public ulong ReadOperationCount;
public ulong WriteOperationCount;
public ulong OtherOperationCount;
public ulong ReadTransferCount;
public ulong WriteTransferCount;
public ulong OtherTransferCount;
}
[DllImport("kernel32.dll")]
static extern bool GetProcessIoCounters(IntPtr ProcessHandle, out IO_COUNTERS IoCounters);
public static void Main()
{
IO_COUNTERS counters;
GetProcessIoCounters(System.Diagnostics.Process.GetCurrentProcess().Handle, out counters);
Console.WriteLine("This process has read " + counters.ReadTransferCount.ToString("N0") +
" bytes of data.");
Console.ReadKey();
}
}