From 0aaafa91b2b70bf131009bdcc016d1ebea3a0218 Mon Sep 17 00:00:00 2001
From: albert-du <52804499+albert-du@users.noreply.github.com>
Date: Sat, 19 Feb 2022 16:56:05 -0800
Subject: [PATCH] IntPtr F# snippets
---
snippets/fsharp/System/IntPtr/Add/add1.fs | 25 ++++++++++
snippets/fsharp/System/IntPtr/Add/fs.fsproj | 10 ++++
.../fsharp/System/IntPtr/Overview/fs.fsproj | 10 ++++
.../System/IntPtr/Overview/topointer.fs | 49 +++++++++++++++++++
.../fsharp/System/IntPtr/Subtract/fs.fsproj | 10 ++++
.../System/IntPtr/Subtract/subtract1.fs | 24 +++++++++
.../fsharp/System/IntPtr/ToPointer/fs.fsproj | 10 ++++
.../System/IntPtr/ToPointer/topointer.fs | 49 +++++++++++++++++++
snippets/fsharp/System/IntPtr/Zero/fs.fsproj | 11 +++++
snippets/fsharp/System/IntPtr/Zero/zero2.fs | 19 +++++++
snippets/fsharp/System/IntPtr/Zero/zero4.fs | 33 +++++++++++++
.../System/IntPtr/op_Addition/addition1.fs | 22 +++++++++
.../System/IntPtr/op_Addition/fs.fsproj | 10 ++++
.../op_Addition/op_subtraction/fs.fsproj | 10 ++++
.../IntPtr/op_Addition/op_subtraction1.fs | 22 +++++++++
xml/System/IntPtr.xml | 16 ++++--
16 files changed, 326 insertions(+), 4 deletions(-)
create mode 100644 snippets/fsharp/System/IntPtr/Add/add1.fs
create mode 100644 snippets/fsharp/System/IntPtr/Add/fs.fsproj
create mode 100644 snippets/fsharp/System/IntPtr/Overview/fs.fsproj
create mode 100644 snippets/fsharp/System/IntPtr/Overview/topointer.fs
create mode 100644 snippets/fsharp/System/IntPtr/Subtract/fs.fsproj
create mode 100644 snippets/fsharp/System/IntPtr/Subtract/subtract1.fs
create mode 100644 snippets/fsharp/System/IntPtr/ToPointer/fs.fsproj
create mode 100644 snippets/fsharp/System/IntPtr/ToPointer/topointer.fs
create mode 100644 snippets/fsharp/System/IntPtr/Zero/fs.fsproj
create mode 100644 snippets/fsharp/System/IntPtr/Zero/zero2.fs
create mode 100644 snippets/fsharp/System/IntPtr/Zero/zero4.fs
create mode 100644 snippets/fsharp/System/IntPtr/op_Addition/addition1.fs
create mode 100644 snippets/fsharp/System/IntPtr/op_Addition/fs.fsproj
create mode 100644 snippets/fsharp/System/IntPtr/op_Addition/op_subtraction/fs.fsproj
create mode 100644 snippets/fsharp/System/IntPtr/op_Addition/op_subtraction1.fs
diff --git a/snippets/fsharp/System/IntPtr/Add/add1.fs b/snippets/fsharp/System/IntPtr/Add/add1.fs
new file mode 100644
index 00000000000..ee6cae7830c
--- /dev/null
+++ b/snippets/fsharp/System/IntPtr/Add/add1.fs
@@ -0,0 +1,25 @@
+//
+#nowarn "9"
+open System
+open System.Runtime.InteropServices
+open FSharp.NativeInterop
+
+[]
+let main _ =
+ let mutable arr =
+ [| 2; 4; 6; 8; 10; 12; 14; 16; 18; 20 |]
+
+ use parr = fixed arr
+
+ let ptr = NativePtr.toNativeInt parr
+
+ // Get the size of an array element.
+ let size = sizeof
+ for i = 0 to arr.Length - 1 do
+ let newPtr = IntPtr.Add(ptr, i * size)
+ printf $"{Marshal.ReadInt32 newPtr} "
+ 0
+
+// The example displays the following output:
+// 2 4 6 8 10 12 14 16 18 20
+//
\ No newline at end of file
diff --git a/snippets/fsharp/System/IntPtr/Add/fs.fsproj b/snippets/fsharp/System/IntPtr/Add/fs.fsproj
new file mode 100644
index 00000000000..95dfad9f45c
--- /dev/null
+++ b/snippets/fsharp/System/IntPtr/Add/fs.fsproj
@@ -0,0 +1,10 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
+
\ No newline at end of file
diff --git a/snippets/fsharp/System/IntPtr/Overview/fs.fsproj b/snippets/fsharp/System/IntPtr/Overview/fs.fsproj
new file mode 100644
index 00000000000..e7429e6eb62
--- /dev/null
+++ b/snippets/fsharp/System/IntPtr/Overview/fs.fsproj
@@ -0,0 +1,10 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
+
\ No newline at end of file
diff --git a/snippets/fsharp/System/IntPtr/Overview/topointer.fs b/snippets/fsharp/System/IntPtr/Overview/topointer.fs
new file mode 100644
index 00000000000..3c0280b4a9c
--- /dev/null
+++ b/snippets/fsharp/System/IntPtr/Overview/topointer.fs
@@ -0,0 +1,49 @@
+//
+#nowarn "9"
+open System.Runtime.InteropServices
+open FSharp.NativeInterop
+
+[]
+let main _ =
+ let stringA = "I seem to be turned around!"
+ let mutable copylen = stringA.Length
+
+ // Allocate HGlobal memory for source and destination strings
+ let sptr = Marshal.StringToHGlobalAnsi stringA
+ let dptr = Marshal.AllocHGlobal(copylen + 1)
+
+ let mutable src: byte nativeptr = sptr.ToPointer() |> NativePtr.ofVoidPtr
+ let mutable dst: byte nativeptr = dptr.ToPointer() |> NativePtr.ofVoidPtr
+
+ if copylen > 0 then
+ // set the source pointer to the end of the string
+ // to do a reverse copy.
+ src <-
+ NativePtr.toNativeInt src + nativeint (copylen - 1)
+ |> NativePtr.ofNativeInt
+
+ while copylen > 0 do
+ copylen <- copylen - 1
+ NativePtr.read src |> NativePtr.write dst
+ dst <- NativePtr.toNativeInt dst + 1n |> NativePtr.ofNativeInt
+ src <- NativePtr.toNativeInt src - 1n |> NativePtr.ofNativeInt
+ NativePtr.write dst 0uy
+
+ let stringB = Marshal.PtrToStringAnsi dptr
+
+ printfn $"Original:\n{stringA}\n"
+ printfn $"Reversed:\n{stringB}"
+
+ // Free HGlobal memory
+ Marshal.FreeHGlobal dptr
+ Marshal.FreeHGlobal sptr
+ 0
+
+// The progam has the following output:
+//
+// Original:
+// I seem to be turned around!
+//
+// Reversed:
+// !dnuora denrut eb ot mees I
+//
\ No newline at end of file
diff --git a/snippets/fsharp/System/IntPtr/Subtract/fs.fsproj b/snippets/fsharp/System/IntPtr/Subtract/fs.fsproj
new file mode 100644
index 00000000000..d00db14a81b
--- /dev/null
+++ b/snippets/fsharp/System/IntPtr/Subtract/fs.fsproj
@@ -0,0 +1,10 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
+
\ No newline at end of file
diff --git a/snippets/fsharp/System/IntPtr/Subtract/subtract1.fs b/snippets/fsharp/System/IntPtr/Subtract/subtract1.fs
new file mode 100644
index 00000000000..c8f1b583444
--- /dev/null
+++ b/snippets/fsharp/System/IntPtr/Subtract/subtract1.fs
@@ -0,0 +1,24 @@
+//
+#nowarn "9"
+open System
+open System.Runtime.InteropServices
+open FSharp.NativeInterop
+
+[]
+let main _ =
+ let arr =
+ [| 2; 4; 6; 8; 10; 12; 14; 16; 18; 20 |]
+
+ // Get the size of a single array element.
+ let size = sizeof
+
+ use pend = fixed &arr[arr.GetUpperBound 0]
+ let ptr = NativePtr.toNativeInt pend
+ for i = 0 to arr.Length - 1 do
+ let newPtr = IntPtr.Subtract(ptr, i * size)
+ printf $"{Marshal.ReadInt32 newPtr} "
+ 0
+
+// The example displays the following output:
+// 20 18 16 14 12 10 8 6 4 2
+//
\ No newline at end of file
diff --git a/snippets/fsharp/System/IntPtr/ToPointer/fs.fsproj b/snippets/fsharp/System/IntPtr/ToPointer/fs.fsproj
new file mode 100644
index 00000000000..e7429e6eb62
--- /dev/null
+++ b/snippets/fsharp/System/IntPtr/ToPointer/fs.fsproj
@@ -0,0 +1,10 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
+
\ No newline at end of file
diff --git a/snippets/fsharp/System/IntPtr/ToPointer/topointer.fs b/snippets/fsharp/System/IntPtr/ToPointer/topointer.fs
new file mode 100644
index 00000000000..71706b973ac
--- /dev/null
+++ b/snippets/fsharp/System/IntPtr/ToPointer/topointer.fs
@@ -0,0 +1,49 @@
+//
+#nowarn "9"
+open System.Runtime.InteropServices
+open FSharp.NativeInterop
+
+[]
+let main _ =
+ let stringA = "I seem to be turned around!"
+ let mutable copylen = stringA.Length
+
+ // Allocate HGlobal memory for source and destination strings
+ let sptr = Marshal.StringToHGlobalAnsi stringA
+ let dptr = Marshal.AllocHGlobal(copylen + 1)
+
+ let mutable src: byte nativeptr = sptr.ToPointer() |> NativePtr.ofVoidPtr
+ let mutable dst: byte nativeptr = dptr.ToPointer() |> NativePtr.ofVoidPtr
+
+ if copylen > 0 then
+ // set the source pointer to the end of the string
+ // to do a reverse copy.
+ src <-
+ NativePtr.toNativeInt src + nativeint (copylen - 1)
+ |> NativePtr.ofNativeInt
+
+ while copylen > 0 do
+ copylen <- copylen - 1
+ NativePtr.read src |> NativePtr.write dst
+ dst <- NativePtr.toNativeInt dst + 1n |> NativePtr.ofNativeInt
+ src <- NativePtr.toNativeInt src - 1n |> NativePtr.ofNativeInt
+ NativePtr.write dst 0uy
+
+ let stringB = Marshal.PtrToStringAnsi dptr
+
+ printfn $"Original:\n{stringA}\n"
+ printfn $"Reversed:\n{stringB}"
+
+ // Free HGlobal memory
+ Marshal.FreeHGlobal dptr
+ Marshal.FreeHGlobal sptr
+ 0
+
+// The progam has the following output:
+//
+// Original:
+// I seem to be turned around!
+//
+// Reversed:
+// !dnuora denrut eb ot mees I
+//
\ No newline at end of file
diff --git a/snippets/fsharp/System/IntPtr/Zero/fs.fsproj b/snippets/fsharp/System/IntPtr/Zero/fs.fsproj
new file mode 100644
index 00000000000..b8d86909170
--- /dev/null
+++ b/snippets/fsharp/System/IntPtr/Zero/fs.fsproj
@@ -0,0 +1,11 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/snippets/fsharp/System/IntPtr/Zero/zero2.fs b/snippets/fsharp/System/IntPtr/Zero/zero2.fs
new file mode 100644
index 00000000000..1046ed1fa00
--- /dev/null
+++ b/snippets/fsharp/System/IntPtr/Zero/zero2.fs
@@ -0,0 +1,19 @@
+module zero2
+
+//
+open System
+open System.Runtime.InteropServices
+
+let GW_OWNER = 4
+
+[]
+extern IntPtr GetWindow(nativeint hwnd, int wFlag)
+
+let hwnd = IntPtr 3
+let hOwner = GetWindow(hwnd, GW_OWNER)
+if hOwner = IntPtr.Zero then
+ printfn "Window not found."
+
+// The example displays the following output:
+// Window not found.
+//
\ No newline at end of file
diff --git a/snippets/fsharp/System/IntPtr/Zero/zero4.fs b/snippets/fsharp/System/IntPtr/Zero/zero4.fs
new file mode 100644
index 00000000000..b3319b1fabd
--- /dev/null
+++ b/snippets/fsharp/System/IntPtr/Zero/zero4.fs
@@ -0,0 +1,33 @@
+//
+open Microsoft.Win32.SafeHandles
+open System
+open System.Runtime.InteropServices
+
+let GENERIC_READ = 0x80000000u
+let OPEN_EXISTING = 3u
+let FILE_ATTRIBUTE_NORMAL = 128u
+let FILE_FLAG_OVERLAPPED = 0x40000000u
+
+[]
+extern SafeFileHandle CreateFile(
+ string lpFileName, uint dwDesiredAccess, uint dwShareMode,
+ nativeint pSecurityAttributes, uint dwCreationDisposition,
+ uint dwFlagsAndAttributes, nativeint hTemplateFile)
+
+let hnd =
+ CreateFile("CallOfTheWild.txt", GENERIC_READ, 0u,
+ IntPtr.Zero, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL ||| FILE_FLAG_OVERLAPPED,
+ IntPtr.Zero)
+
+if hnd.IsInvalid then
+ let ex = Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error())
+ printfn $"Attempt to open file failed:\n {ex.Message}"
+else
+ printfn "File successfully opened."
+ hnd.Close()
+
+// If the file cannot be found, the example displays the following output:
+// Attempt to open file failed:
+// The system cannot find the file specified. (Exception from HRESULT: 0x80070002)
+//
\ No newline at end of file
diff --git a/snippets/fsharp/System/IntPtr/op_Addition/addition1.fs b/snippets/fsharp/System/IntPtr/op_Addition/addition1.fs
new file mode 100644
index 00000000000..920bb150794
--- /dev/null
+++ b/snippets/fsharp/System/IntPtr/op_Addition/addition1.fs
@@ -0,0 +1,22 @@
+//
+#nowarn "9"
+open System.Runtime.InteropServices
+open FSharp.NativeInterop
+
+[]
+let main _ =
+ let arr =
+ [| 2; 4; 6; 8; 10; 12; 14; 16; 18; 20 |]
+
+ use parr = fixed arr
+
+ let ptr = NativePtr.toNativeInt parr
+
+ for i = 0 to arr.Length - 1 do
+ let newPtr = ptr + nativeint i * nativeint sizeof
+ printf $"{Marshal.ReadInt32 newPtr} "
+ 0
+
+ // The example displays the following output:
+ // 2 4 6 8 10 12 14 16 18 20
+ //
\ No newline at end of file
diff --git a/snippets/fsharp/System/IntPtr/op_Addition/fs.fsproj b/snippets/fsharp/System/IntPtr/op_Addition/fs.fsproj
new file mode 100644
index 00000000000..9c04df12a62
--- /dev/null
+++ b/snippets/fsharp/System/IntPtr/op_Addition/fs.fsproj
@@ -0,0 +1,10 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
+
\ No newline at end of file
diff --git a/snippets/fsharp/System/IntPtr/op_Addition/op_subtraction/fs.fsproj b/snippets/fsharp/System/IntPtr/op_Addition/op_subtraction/fs.fsproj
new file mode 100644
index 00000000000..2a88d71e17e
--- /dev/null
+++ b/snippets/fsharp/System/IntPtr/op_Addition/op_subtraction/fs.fsproj
@@ -0,0 +1,10 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
+
\ No newline at end of file
diff --git a/snippets/fsharp/System/IntPtr/op_Addition/op_subtraction1.fs b/snippets/fsharp/System/IntPtr/op_Addition/op_subtraction1.fs
new file mode 100644
index 00000000000..0d242b8c688
--- /dev/null
+++ b/snippets/fsharp/System/IntPtr/op_Addition/op_subtraction1.fs
@@ -0,0 +1,22 @@
+//
+#nowarn "9"
+open System.Runtime.InteropServices
+open FSharp.NativeInterop
+
+[]
+let main _ =
+ let arr =
+ [| 2; 4; 6; 8; 10; 12; 14; 16; 18; 20 |]
+
+ use parr = fixed &arr[arr.GetUpperBound 0]
+
+ let ptr = NativePtr.toNativeInt parr
+
+ for i = 0 to arr.GetUpperBound 0 do
+ let newPtr = ptr - nativeint i * nativeint sizeof
+ printf $"{Marshal.ReadInt32 newPtr} "
+ 0
+
+ // The example displays the following output:
+ // 20 18 16 14 12 10 8 6 4 2
+ //
\ No newline at end of file
diff --git a/xml/System/IntPtr.xml b/xml/System/IntPtr.xml
index 19e36f817dd..8f24bd365f5 100644
--- a/xml/System/IntPtr.xml
+++ b/xml/System/IntPtr.xml
@@ -114,19 +114,19 @@
The following example uses managed pointers to reverse the characters in an array. After it initializes a object and gets its length, it does the following:
-1. Calls the method to copy the Unicode string to unmanaged memory as an ANSI (one-byte) character. The method returns an object that points to the beginning of the unmanaged string. The Visual Basic example uses this pointer directly; in the C++ and C# examples, it is cast to a pointer to a byte.
+1. Calls the method to copy the Unicode string to unmanaged memory as an ANSI (one-byte) character. The method returns an object that points to the beginning of the unmanaged string. The Visual Basic example uses this pointer directly; in the C++, F# and C# examples, it is cast to a pointer to a byte.
-2. Calls the method to allocate the same number of bytes as the unmanaged string occupies. The method returns an object that points to the beginning of the unmanaged block of memory. The Visual Basic example uses this pointer directly; in the C++ and C# examples, it is cast to a pointer to a byte.
+2. Calls the method to allocate the same number of bytes as the unmanaged string occupies. The method returns an object that points to the beginning of the unmanaged block of memory. The Visual Basic example uses this pointer directly; in the C++, F# and C# examples, it is cast to a pointer to a byte.
3. The Visual Basic example defines a variable named `offset` that is equal to the length of the ANSI string. It is used to determine the offset into unmanaged memory to which the next character in the ANSI string is copied. Because its starting value is the length of the string, the copy operation will copy a character from the start of the string to the end of the memory block.
- The C# and C++ examples call the method to get an unmanaged pointer to the starting address of the string and the unmanaged block of memory, and they add one less than the length of the string to the starting address of the ANSI string. Because the unmanaged string pointer now points to the end of the string, the copy operation will copy a character from the end of the string to the start of the memory block.
+ The C#, F# and C++ examples call the method to get an unmanaged pointer to the starting address of the string and the unmanaged block of memory, and they add one less than the length of the string to the starting address of the ANSI string. Because the unmanaged string pointer now points to the end of the string, the copy operation will copy a character from the end of the string to the start of the memory block.
4. Uses a loop to copy each character from the string to the unmanaged block of memory.
The Visual Basic example calls the method to read the byte (or one-byte character) at a specified offset from the managed pointer to the ANSI string. The offset is incremented with each iteration of the loop. It then calls the method to write the byte to the memory address defined by the starting address of the unmanaged block of memory plus `offset`. It then decrements `offset`.
- The C# and C++ examples perform the copy operation, then decrement the pointer to the address of the next location in the unmanaged ANSI string and increment the pointer to the next address in the unmanaged block.
+ The C#, F# and C++ examples perform the copy operation, then decrement the pointer to the address of the next location in the unmanaged ANSI string and increment the pointer to the next address in the unmanaged block.
5. All examples call the to convert the unmanaged memory block containing the copied ANSI string to a managed Unicode object.
@@ -134,6 +134,7 @@
:::code language="cpp" source="~/snippets/cpp/VS_Snippets_CLR_System/system.intptr/cpp/topointer.cpp" id="Snippet1":::
:::code language="csharp" source="~/snippets/csharp/System/IntPtr/ToPointer/topointer.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/snippets/fsharp/System/IntPtr/ToPointer/topointer.fs" id="Snippet1":::
:::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.intptr/vb/topointer.vb" id="Snippet1":::
]]>
@@ -396,6 +397,7 @@
The following example instantiates an object that points to the beginning of a ten-element array, and then calls the method to iterate the elements in the array.
:::code language="csharp" source="~/snippets/csharp/System/IntPtr/Add/add1.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/snippets/fsharp/System/IntPtr/Add/add1.fs" id="Snippet1":::
:::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.intptr.add/vb/add1.vb" id="Snippet1":::
]]>
@@ -751,6 +753,7 @@
The method defines the addition operation for objects. It enables code such as the following.
:::code language="csharp" source="~/snippets/csharp/System/IntPtr/op_Addition/addition1.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/snippets/fsharp/System/IntPtr/op_Addition/addition1.fs" id="Snippet1":::
:::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.intptr.op_addition/vb/addition1.vb" id="Snippet1":::
Languages that do not support custom operators can call the method instead.
@@ -1324,6 +1327,7 @@
The method defines the subtraction operation for objects. It enables code such as the following.
:::code language="csharp" source="~/snippets/csharp/System/IntPtr/op_Addition/op_subtraction1.cs" id="Snippet2":::
+ :::code language="fsharp" source="~/snippets/fsharp/System/IntPtr/op_Addition/op_subtraction1.fs" id="Snippet2":::
:::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.intptr.op_addition/vb/op_subtraction1.vb" id="Snippet2":::
Languages that do not support custom operators can call the method instead.
@@ -1658,6 +1662,7 @@
The following example instantiates an object that points to the end of a ten-element array, and then calls the method to iterate the elements in the array in reverse order.
:::code language="csharp" source="~/snippets/csharp/System/IntPtr/Subtract/subtract1.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/snippets/fsharp/System/IntPtr/Subtract/subtract1.fs" id="Snippet1":::
:::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.intptr.subtract/vb/subtract1.vb" id="Snippet1":::
]]>
@@ -1961,6 +1966,7 @@ This member is an explicit interface member implementation. It can be used only
:::code language="cpp" source="~/snippets/cpp/VS_Snippets_CLR_System/System.IntPtr.ToPointer/cpp/topointer.cpp" id="Snippet1":::
:::code language="csharp" source="~/snippets/csharp/System/IntPtr/Overview/topointer.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/snippets/fsharp/System/IntPtr/Overview/topointer.fs" id="Snippet1":::
]]>
@@ -2405,6 +2411,7 @@ This member is an explicit interface member implementation. It can be used only
When calling the Windows API from managed code, you can pass instead of `null` if an argument is expected to be either a pointer or a `null`. For example, the following call to the Windows `CreateFile` function supplies for the `pSecurityAttributes` and `hTemplateFile` argument values.
:::code language="csharp" source="~/snippets/csharp/System/IntPtr/Zero/zero4.cs" id="Snippet2":::
+ :::code language="fsharp" source="~/snippets/fsharp/System/IntPtr/Zero/zero4.fs" id="Snippet2":::
:::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.intptr.zero/vb/zero4.vb" id="Snippet2":::
> [!NOTE]
@@ -2413,6 +2420,7 @@ This member is an explicit interface member implementation. It can be used only
You can also test for a `null` return value from Windows API function calls that return either a pointer or a `null` by comparing the returned value with . For example, the call to the `GetWindow` function in the following example tries to retrieve the handle of a non-existent window. If it were called from unmanaged code, the function would return `null`, but when it is called from managed code, it returns .
:::code language="csharp" source="~/snippets/csharp/System/IntPtr/Zero/zero2.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/snippets/fsharp/System/IntPtr/Zero/zero2.fs" id="Snippet1":::
:::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.intptr.zero/vb/zero2.vb" id="Snippet1":::
]]>