Unsafe Context

/*
A Programmer's Introduction to C# (Second Edition)
by Eric Gunnerson

Publisher: Apress L.P.
ISBN: 1-893115-62-3
*/
// 36 – Deeper into C#Unsafe Context
// copyright 2000 Eric Gunnerson
// file=unsafe.cs
// compile with: csc /unsafe /o+ unsafe.cs
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

public class UnsafeContext
{
const int iterations = 20000; // # to do copy
const int points = 1000; // # of points in array
const int retryCount = 5; // # of times to retry

public delegate Point[] CloneFunction(Point[] a);

public static void TimeFunction(Point[] arr,
CloneFunction func, string label)
{
Point[] arrCopy = null;
long start;
long delta;
double min = 5000.0d; // big number;

// do the whole copy retryCount times, find fastest time
for (int retry = 0; retry < retryCount; retry++) { start = Counter.Value; for (int iterate = 0; iterate < iterations; iterate++) arrCopy = func(arr); delta = Counter.Value - start; double result = (double) delta / Counter.Frequency; if (result < min) min = result; } Console.WriteLine("{0}: {1:F3} seconds", label, min); } public static void Main() { Console.WriteLine("Points, Iterations: {0} {1}", points, iterations); Point[] arr = new Point[points]; for (int index = 0; index < points; index++) arr[index] = new Point(3, 5); TimeFunction(arr, new CloneFunction(Point.ClonePointArrayMemcpy), "Memcpy"); TimeFunction(arr, new CloneFunction(Point.ClonePointArrayUnsafe), "Unsafe"); TimeFunction(arr, new CloneFunction(Point.ClonePointArray), "Baseline"); } } class Counter { public static long Frequency { get { long freq = 0; QueryPerformanceFrequency(ref freq); return freq; } } public static long Value { get { long count = 0; QueryPerformanceCounter(ref count); return count; } } [System.Runtime.InteropServices.DllImport("KERNEL32", CharSet=System.Runtime.InteropServices.CharSet.Auto)] private static extern bool QueryPerformanceCounter( ref long lpPerformanceCount); [System.Runtime.InteropServices.DllImport("KERNEL32", CharSet=System.Runtime.InteropServices.CharSet.Auto)] private static extern bool QueryPerformanceFrequency( ref long lpFrequency); } public struct Point { public Point(int x, int y) { this.x = x; this.y = y; } // safe version public static Point[] ClonePointArray(Point[] a) { Point[] ret = new Point[a.Length]; for (int index = 0; index < a.Length; index++) ret[index] = a[index]; return(ret); } // unsafe version using pointer arithmetic unsafe public static Point[] ClonePointArrayUnsafe(Point[] a) { Point[] ret = new Point[a.Length]; // a and ret are pinned; they cannot be moved by // the garbage collector inside the fixed block. fixed (Point* src = a, dest = ret) { Point* pSrc = src; Point* pDest = dest; for (int index = 0; index < a.Length; index++) { *pDest = *pSrc; pSrc++; pDest++; } } return(ret); } // import CopyMemory from kernel32 [DllImport("kernel32.dll")] unsafe public static extern void CopyMemory(void* dest, void* src, int length); // unsafe version calling CopyMemory() unsafe public static Point[] ClonePointArrayMemcpy(Point[] a) { Point[] ret = new Point[a.Length]; fixed (Point* src = a, dest = ret) { CopyMemory(dest, src, a.Length * sizeof(Point)); } return(ret); } public override string ToString() { return(String.Format("({0}, {1})", x, y)); } int x; int y; } [/csharp]

Pointers and Declarative Pinning

   

/*
A Programmer&#039;s Introduction to C# (Second Edition)
by Eric Gunnerson

Publisher: Apress  L.P.
ISBN: 1-893115-62-3
*/
// 31 - InteropCalling Native DLL FunctionsPointers and Declarative Pinning
// copyright 2000 Eric Gunnerson
// file=ReadFileUnsafe.cs
// compile with: csc /unsafe ReadFileUnsafe.cs
using System;
using System.Runtime.InteropServices;
using System.Text;

class FileRead
{
    const uint GENERIC_READ = 0x80000000;
    const uint OPEN_EXISTING = 3;
    int handle;
    
    public FileRead(string filename)
    {
        // opens the existing file
        handle = CreateFile(    filename,
        GENERIC_READ,
        0, 
        0,
        OPEN_EXISTING,
        0,
        0);
    }
    
    [DllImport("kernel32", SetLastError=true)]
    static extern int CreateFile(
    string filename,
    uint desiredAccess,
    uint shareMode,
    uint attributes,        // really SecurityAttributes pointer
    uint creationDisposition,
    uint flagsAndAttributes,
    uint templateFile);
    
    [DllImport("kernel32", SetLastError=true)]
    static extern unsafe bool ReadFile(
    int hFile,
    void* lpBuffer, 
    int nBytesToRead,
    int* nBytesRead,
    int overlapped);
    
    public unsafe int Read(byte[] buffer, int count)
    {
        int n = 0;
        fixed (byte* p = buffer) 
        {
            ReadFile(handle, p, count, &amp;n, 0);
        }
        return n;
    }
}
public class PointersandDeclarativePinning
{
    public static void Main(string[] args)
    {
        FileRead fr = new FileRead(args[0]);
        
        byte[] buffer = new byte[128];
        ASCIIEncoding e = new ASCIIEncoding();
        
        // loop through, read until done
        Console.WriteLine("Contents");
        while (fr.Read(buffer, 128) != 0)
        {
            Console.Write("{0}", e.GetString(buffer));
        }
    }
}

           
          


Unsafe code: copy

/*
C# Programming Tips & Techniques
by Charles Wright, Kris Jamsa

Publisher: Osborne/McGraw-Hill (December 28, 2001)
ISBN: 0072193794
*/
namespace nsType
{
using System;

public class IntCopy
{
public static void Main ()
{
int [] arr1 = new int[] {1, 4, 2, 8, 5, 7};
int [] arr2 = new int[arr1.Length];
MemCpy (arr2, arr1, arr1.Length);
arr1[0] = 142857;
for (int x = 0; x < arr1.Length; ++x) { Console.Write ("arr1[{0}] = {1} ", x, arr1[x]); Console.Write ("arr2[{0}] = {1} ", x, arr2[x]); } } static unsafe public void MemCpy (int [] dst, int [] src, int size) { if ((size > dst.Length) || (size > src.Length))
{
ArgumentException e = new ArgumentException(“The size argument is too large for one of the array arguments”);
throw (e);
}
fixed (int *Src = src, Dst = dst)
{
int* pSrc = Src;
int* pDst = Dst;
for (int n = 0; n < size; ++n) { *pDst++ = *pSrc++; } } } } } [/csharp]

Multiple Indirect


   

/*
C#: The Complete Reference 
by Herbert Schildt 

Publisher: Osborne/McGraw-Hill (March 8, 2002)
ISBN: 0072134852
*/


using System; 
 
public class MultipleIndirect { 
  unsafe public static void Main() { 
    int x;    // holds a int value  
    int* p;  // holds an int pointer 
    int** q; // holds an pointer to an int pointer 
 
    x = 10; 
    p = &amp;x; // put address of x into p 
    q = &amp;p; // put address of p into q 
 
    Console.WriteLine(**q); // display the value of x  
  } 
}


           
          


Use fixed to get a pointer to the start of a string


   

/*
C#: The Complete Reference 
by Herbert Schildt 

Publisher: Osborne/McGraw-Hill (March 8, 2002)
ISBN: 0072134852
*/


// Use fixed to get a pointer to the start of a string. 
 
using System; 
 
public class FixedString { 
  unsafe public static void Main() { 
    string str = "this is a test"; 
 
    // Point p to start of str. 
    fixed(char* p = str) { 
 
      // Display the contents of str via p. 
      for(int i=0; p[i] != 0; i++) 
        Console.Write(p[i]); 
    } 
 
    Console.WriteLine(); 
     
  } 
}


           
          


Index a pointer as if it were an array

/*
C#: The Complete Reference
by Herbert Schildt

Publisher: Osborne/McGraw-Hill (March 8, 2002)
ISBN: 0072134852
*/

// Index a pointer as if it were an array.

using System;

public class PtrIndexDemo {
unsafe public static void Main() {
int[] nums = new int[10];

// index pointer
Console.WriteLine(“Index pointer like array.”);
fixed (int* p = nums) {
for(int i=0; i < 10; i++) p[i] = i; // index pointer like array for(int i=0; i < 10; i++) Console.WriteLine("p[{0}]: {1} ", i, p[i]); } // use pointer arithmetic Console.WriteLine(" Use pointer arithmetic."); fixed (int* p = nums) { for(int i=0; i < 10; i++) *(p+i) = i; // use pointer arithmetic for(int i=0; i < 10; i++) Console.WriteLine("*(p+{0}): {1} ", i, *(p+i)); } } } [/csharp]

An array name with an index yields a pointer to the start of the array


   

/*
C#: The Complete Reference 
by Herbert Schildt 

Publisher: Osborne/McGraw-Hill (March 8, 2002)
ISBN: 0072134852
*/


/* An array name with an index yields a pointer to the 
   start of the array. */ 
 
using System; 
 
public class PtrArray { 
  unsafe public static void Main() { 
    int[] nums = new int[10]; 
 
    fixed(int* p = &amp;nums[0], p2 = nums) { 
      if(p == p2) 
        Console.WriteLine("p and p2 point to same address."); 
    } 
  } 
}