using System; class Operators { static void Main() { #line 300 #warning Something happened. #warning Something else happened. #line 400 "someotherfile.cs" #warning Something happened later. #line default #warning Nothing else will happen. } }
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'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, &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 = &x; // put address of x into p q = &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]