VB6のVarPtr, StrPtr, ObjPtr関数は変数の下位のメモリアドレスを取得するためのドキュメント化されていない関数です。「Visual Basic .NET へのアップグレードを円滑に行うための Visual Basic 6.0 アプリケーションの準備」や「VB 6.0 ユーザーのための VB .NET 移行ガイド - レガシー機能」によると、これらの関数はVB.NETではサポートされていないとのことです。
.NETではこれらの機能が必要になる機会はそうはないでしょうが、.NETでもオブジェクトのアドレスを取得することは可能です。しかしこのとき問題になるのは、アドレスを取得し、それを使用する間、共通言語ライブラリ(CLR)によってこのアドレスが変更されないことを確実にしなければならないということです。共通言語ライブラリはガベージコレクタによって、効率化のためにオブジェクトをメモリ内で移動しているのです。
そのため、オブジェクトのアドレスはGCHandle.AddrOfPinnedObjectメソッドで取得し、このときに必要なハンドルはGCHandle.Allocメソッドで取得します。使い終わった後はGCHandle.Freeメソッドによりハンドルを解放します。
次のサンプルは、オブジェクト"obj"のアドレスを取得するものです。
'Imports System.Runtime.InteropServices 'がソースファイルの一番上に書かれているものとする 'ガベージコレクタがオブジェクトを移動できないようにする Dim gch As GCHandle = GCHandle.Alloc(obj, GCHandleType.Pinned) '固定オブジェクトのアドレスを取得する Dim address As Integer = gch.AddrOfPinnedObject().ToInt32() 'ハンドルを解放する 'オブジェクトの移動ができるようになる gch.Free()
//using System.Runtime.InteropServices; //がソースファイルの一番上に書かれているものとする //ガベージコレクタがオブジェクトを移動できないようにする GCHandle gch = GCHandle.Alloc(obj, GCHandleType.Pinned); //固定オブジェクトのアドレスを取得する int address = gch.AddrOfPinnedObject().ToInt32(); //ハンドルを解放する //オブジェクトの移動ができるようになる gch.Free();
(この記事は「.NETプログラミング研究 第27号」で紹介したものです。)