DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

VarPtr, StrPtr, ObjPtr関数の代わりになるものは?

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"のアドレスを取得するものです。

VB.NET
コードを隠すコードを選択
'Imports System.Runtime.InteropServices
'がソースファイルの一番上に書かれているものとする

'ガベージコレクタがオブジェクトを移動できないようにする
Dim gch As GCHandle = GCHandle.Alloc(obj, GCHandleType.Pinned)
'固定オブジェクトのアドレスを取得する
Dim address As Integer = gch.AddrOfPinnedObject().ToInt32()

'ハンドルを解放する
'オブジェクトの移動ができるようになる
gch.Free()
C#
コードを隠すコードを選択
//using System.Runtime.InteropServices;
//がソースファイルの一番上に書かれているものとする

//ガベージコレクタがオブジェクトを移動できないようにする
GCHandle gch = GCHandle.Alloc(obj, GCHandleType.Pinned);
//固定オブジェクトのアドレスを取得する
int address = gch.AddrOfPinnedObject().ToInt32();

//ハンドルを解放する
//オブジェクトの移動ができるようになる
gch.Free();

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。