全ての列挙体をタイプ定義に一括変更

Tips

スポンサーリンク

この記事で扱っていること

  • 全ての列挙体をタイプ定義に一括変更する方法

を紹介しています。

LabVIEWでプログラムを作る上で基本の型となるデザインパターンの一つであるステートマシンは、後からプログラムに変更が生じ機能を追加したい場合でもタイプ定義された列挙体を使えば容易に機能変更を行えます。

ただ、最初は機能追加などしないものと考えて列挙体をタイプ定義するのを忘れた状態である程度プログラムを作り、後悔する羽目になるということもあり得ると思うのです(実体験より)。

ステートマシンでなくても、機能的グローバル変数なんかでも列挙体を使うと思いますが、なんにせよ後からタイプ定義した列挙体に置換しなおすのは結構面倒です。

こういった、タイプ定義されていない列挙体をタイプ定義に変換する場合、手作業で行うのは面倒だということで、プログラム的に列挙体をタイプ定義に変換する方法を考えました。

なお、プログラムの性質上、再帰処理を用いています。

スポンサーリンク

どんな結果になるか

変換するためのプログラムのフロントパネルはシンプルで、変換対象のVIのパスと、どのタイプ定義列挙体で変換したいかを指定するためにそのタイプ定義(ctlファイル)のパスを指定します。

簡単な例として、以下の図のような構造を持つステートマシンのプログラムを変換対象のVIとします。

プログラムを実行し変換後、列挙体がタイプ定義されたものに置き換わっているのがわかると思います。

また、変換対象のVIにある程度複雑なプログラム、具体的にはWhileループの中にステートマシン、その中にまたWhileループがある、といったような入れ子構造を持つプログラムであっても、変換することができます。

プログラムの構造

こうした、他のVIのブロックダイアグラムを編集するプログラムは、VIスクリプトの機能を使う必要があります。

VIのリファレンスを開いて、そこからプロパティノードを使用して指定したVIのダイアグラムの情報にアクセスし、その「すべてのオブジェクト」のリファレンスを取得しています。

VIスクリプトの関数、機能を使用するためには、LabVIEWのメニューバーの「ツール」にある「オプション」を開いて、VIサーバカテゴリにあるVIスクリプトの機能を有効(デフォルトだとチェックが入ってないのでチェックを入れる)にします。

プログラムを作る上で注意する必要があるのは、プロパティノードで「すべてのオブジェクト」を使用して得られたリファレンスは、ストラクチャ要素(関数パレットで「ストラクチャ」のカテゴリに入っている、Whileループやケースストラクチャなど)の外側だけのリファレンスしか取得できない、という点です。

例えば、例として挙げた変換対象プログラムに対しては「すべてのオブジェクト」として得られるのはWhileループの左側の列挙体定数とWhileループのリファレンスのみで、Whileループの中身のケースストラクチャやさらにその中にある数値や列挙体の定数のリファレンスは取得できません。

変換対象とするプログラムが必ず特定の構造をもっている、ということであれば、「Whileループのリファレンスを使って、Whileループ内のオブジェクトのリファレンスを取得する」というプログラムを書けばいいですが、これでは特定の構造をもったVIしか変換対象にできません。

そうではなく、Whileループやケースストラクチャがどれだけ入れ子になっていても変換できれば便利です。

そんなときに役立つのが再帰処理で、今回のプログラムではこの再帰処理を用います。 もし再帰処理自体について知りたいという場合には以下の記事が参考になるかもしれません。

というわけで、今回のプログラムのブロックダイアグラムにあるstructure_recursive.viは再帰処理ができるようなサブVIとしています。

ブロックダイアグラムは以下のようにしており、入力としてリファレンスを受け取り、プロパティノードに渡してクラス名を取得しています。

そしてこのクラス名から、どのオブジェクトに対するリファレンスかを特定し、そのオブジェクトの種類ごとに処理を変えます。

今回前提としているのはWhileループとケースストラクチャのみです。

ステートマシンで最も基本的な要素となるのがこれらだからですが、もし変換対象のプログラムにForループが使われている、ということであればForループに対するケースも追加することになります。

特定の「ストラクチャ」に対応するケースストラクチャでの指定(ラベル名)がわからない、という場合には、そのストラクチャ単体のVIを作成し、このVIのブロックダイアグラムの「すべてのオブジェクト」に対してクラス名を取得すれば、どのような文字でラベル名(下の図でいうところの「EnumConstant」や「WhileLoop」など)を書いたらいいか確認できます。

お気づきの方もいるかと思いますが、このプログラムは列挙体であればなんでも変換することに注意してください。

ステートマシンと関係がない(指定したタイプ定義の列挙体とは別の項目を持つ)列挙体についても変換をします。

もし上記のブロックダイアグラムのように関数を配置した際に、WhileLoopとCaseStructureの中身でstructure_recursive.viの表示がグレーアウトしてしまっているのであれば、再帰処理の設定ができていないということなので、VIプロパティにてクローン設定を忘れずに行っておいてください。

変換後に自動で保存する場合

上で紹介したプログラムは列挙体をタイプ定義した列挙体に変換してくれるのですが、実はこれだけだと「変換するけれど保存しない」状態となります。

なので、例えば変換対象のVIのブロックダイアグラムを開いたまま今回のプログラムを実行すると、列挙体に変換される様子がわかるものの、VI自体は未保存状態となります。

そうではなく、変換後に変換し終わったプログラムを保存したいということであれば、インボークノードを使用して以下のようにプログラムを組めば対応できます。

本記事では、全ての列挙体をタイプ定義に一括変更する方法を紹介しました。

似た方法を使えば、列挙体以外のものだって一括で変換することはできると思いますが、特にあったら便利だなというプログラムの例として列挙体を題材にしてみました。参考になればうれしいです。

ここまで読んでいただきありがとうございました。

コメント

タイトルとURLをコピーしました