注釈: この記事は、Dereferencing Pointers from C/C++ DLLs in LabVIEW を翻訳したものです。内容に相違がある場合、英語の資料が正文となっております。
概観
多くのC/C++関数は、実際のデータを保持するメモリアドレスへのポインタ(またはリファレンス)の形でデータを戻します。プログラマは、ポインタをデリファレンスすることでメモリアドレスに保持された値を取得します。しかし、LabVIEWはメモリ管理をユーザに制限しているため、LabVIEWでポインタをデリファレンスするためには特殊な手法が必要です。
メモ:数値やシンプルな構造体などのLabVIEWの一般的なデータタイプへのポインタは、ライブラリ関数呼び出しノードで自動的にデリファレンスすることが可能です。詳細は、LabVIEWでC/C++のDLLにポインタを渡したり受け取るのポインタを受け取り自動的にデリファレンスセクションを参照してください。
LabVIEWはポインタをデリファレンスするために2つの選択肢を用意しています。
- MoveBlock関数: 下位、高い操作性、全てのデータタイプに適応
- GetValueByPointer関数: 使いやすく、タイプに適応、一部の複雑なデータタイプには非対応
オプション1: MoveBlock関数
MoveBlockは、メモリアドレスが入力されると、そのアドレスのデータ値を返すMemory Manager関数です。ユーザは、MoveBlock関数が読み取るバイト数や、読み取ったデータを変換するデータタイプを指定することが可能です。このような下位レベルの操作性により、シンプルな数値から、配列やほかのクラスタを含むクラスタなどをデリファレンスできます。
MoveBlockを呼び出すためには下記の手順を実行します:
- ブロックダイアグラムを開く
- ライブラリ関数呼び出しノードを配置
(関数パレット » コネクティビティ » ライブラリと実行 » ライブラリ関数呼び出しノード)
- ライブラリ名またはパスに、LabVIEWと入力
- これにより関数名が追加されます
- 関数名リストボックスからMoveBlockを選択
- パラメータタブに移動
- パラメータを下記の通りに設定:
名前 |
タイプ |
データタイプ・ フォーマット |
パス |
返り値タイプ |
Void |
|
|
Address (Pointer) |
数値 |
符号付きポインタサイズ整数 |
値へのポインタ |
Destination |
タイプに適応 |
<データにより変動> |
|
Size |
数値 |
符号付きポインタサイズ整数 |
値 |
- OKをクリック
MoveBlockを使用するためには、ポインタをAddressに入力し、デリファレンスされる値と同じデータタイプの定数または制御器をDestinationに入力し、データタイプのサイズ(バイト数)をSizeに配線します。
たとえば、32ビット整数をデリファレンスする場合、ブロックダイアグラムは下記のようになります。
メモ: ポインタへのポインタ(2D配列や文字列配列)をデリファレンスする場合は、特例:2次元配列を参照してください。
オプション2: GetValueByPointer VI
GetValueByPointerは、配線されたデータのデータタイプによって内部的な処理を変更することにより、MoveBlock関数を使用する場合に伴う複雑さを一部軽減する関数です。この関数はMoveBlock関数より使い方は単純ですが、配列や配列を含むクラスタを自動的にデリファレンスすることができません。配列内の要素はひとつずつデリファレンスする必要があります。
GetValueByPointer関数は下記のディレクトリにあります。
<LabVIEW>\vi.lib\Utility\importsl\GetValueByPointer\GetValueByPointer.xnode
この関数は、ポインタをPointer端子に配線し、デリファレンスされるデータと同じデータタイプの定数または制御器をInputType端子に配線して使用します。
例えば、符号付き32ビット整数をデリファレンスする場合、ブロックダイアグラムは下記のようになります。
特例:配列をデリファレンスする
CやC++の配列変数は、配列の1番目の要素へのポインタです。そのため、関数が配列を戻すとき、実際は配列へのポインタを戻しています。配列へのポインタをデリファレンスする場合、MoveBlockかGetValueByPointerのどちらでも使用できます。
例えば、符号付き32ビット整数の配列へのポインタは下記のようにデリファレンスできます。
特例:文字列をデリファレンスする
CやC++の文字列はchar型の配列です。そのため、文字列変数は文字列の1番目の文字へのポインタです。関数が文字列を戻すとき、実際には文字列へのポインタを戻しています。文字列へのポインタをデリファレンスする場合、MoveBlockかGetValueByPointerのどちらでも使用できますが、GetValueByPointerは事前に文字列の長さを指定する必要がないのでMoveBlockより使いやすくなっています。
例えば、文字列へのポインタは下記のようにデリファレンスできます。
特例:2次元配列
2次元配列は配列の配列として表現されています。配列はポインタであるため、2D配列はポインタの配列へのポインタで、配列内の各ポインタは、各行にポイントしています。
そのため、2D配列をデリファレンスするためには、まず各行へのポインタをデリファレンスして、各行の各要素をデリファレンスします。下記のVIスニペットは、この例を示します。
まとめ・次のステップ
この記事ではLabVIEWでポインタをデリファレンスする2つの方法を紹介しました。GetValueByPointerは簡単に使用できますが、自動的に配列や構造体の中の配列を処理できないという制限があります。MoveBlock関数はポインタをデリファレンスする際、フルコントロールを得られる下位レベルの操作性を持つ関数ですが、少々使用方法が複雑です。
2つの関数の使用例については下記の記事を参照してください。
様々なデータタイプを含む C/C++ の DLL を LabVIEW から呼び出す