/* 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)); } } }
Language Basics
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]
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 = &nums[0], p2 = nums) { if(p == p2) Console.WriteLine("p and p2 point to same address."); } } }
Demonstrate pointer comparison
/*
C#: The Complete Reference
by Herbert Schildt
Publisher: Osborne/McGraw-Hill (March 8, 2002)
ISBN: 0072134852
*/
// Demonstrate pointer comparison.
using System;
public class PtrCompDemo {
unsafe public static void Main() {
int[] nums = new int[11];
int x;
// find the middle
fixed (int* start = &nums[0]) {
fixed(int* end = &nums[nums.Length-1]) {
for(x=0; start+x <= end-x; x++) ;
}
}
Console.WriteLine("Middle element is " + x);
}
}
[/csharp]