日本でハリウッドVFXを制作! 「経産省アイディアボックス」 結果:  
●まとめエントリはこちら ●FAQ ●お問い合わせは左のメールフォームから

2010年2月7日日曜日

プロシージャー間での情報のやりとり

先日、シニアの書いたMELをつかえるように直したときに、つぶさに中の流れを観察していて気がついたことがあった。
それは複数のプロシージャをもつスクリプトで、プロシージャ間のデータの受け渡し方法だ。

丁度、同じ頃、他のスクリプトを作っており、実行内容の部分とウインドウ作成部分のプロシージャをわけるようにしていた。
しかしそのときに変数のデータ受け渡しがうまくできなくて多少行き詰まっていた。
シニアの人が書いたスクリプトの流れを追っている内に、いろいろなアイデアが使われていることがわかり、この問題も解決した。

変数はプロシージャ内でつかわれるときには、そのプロシージャー内へスコーピングされている。
他のプロシージャで同じ変数を使用しても、それはまったく独立した存在で、異なるプロシージャ内の変数の値を取得することは出来ない。
参照エントリ: 変数(2)

この異なるプロシージャ間で必要な情報をやりとりするにはいくつかの方法がある。


----------------------------------------
<グローバル変数>

参照:オンラインヘルプ「グローバル変数とローカル変数

グローバル変数を使えば同じ変数を、異なるプロシージャ間で共有出来ます

しかしながら、グローバル変数には、Mayaを再起動するまでメモリに止まり続けるのでも台を引き起こすことがあります。
●たとえば、一度宣言するとMayaを再起動するまで型の変更ができない。
●使用していないときでも、メモリを消費する。



グローバル変数を使うにはには変数宣言のとき、型宣言の前に、「global」と付けます。
使用時には、各プロシージャ内で毎回、変数宣言をする必要があります。

たとえば、以下のようにすると

global proc test1()
{
global int $x1;
$x1 = 1;
}
// ***************

global proc test2()
{
print $x1;
}


エラーになります。
// Error: print $x1; //
// Error: "$x1" is an undeclared variable. //




これはプロシージャ「test2()
の中で$x1が宣言されていないからです。
以下のようにtest2()内でもglobal変数を宣言すればtest1()からの値を受け取って、test2()内のprintコマンドでその内容を表示します。

global proc test1()
{
global int $x1;
$x1 = 1;
}
// ***************

global proc test2()
{
global int $x1;
print $x1;
}



このスクリプトを実行してもなにもおきませんが、
その後
test1;
test2;

と実行すれば「1」と表示されます。


またヘルプにあるではプロシージャ外で、グローバル変数の宣言をしていますが、
これは、そうしなくいと動作しないわけではなく、
その変数名をプロシージャの外に書いておくことで、それがグローバル変数であることを明示するのが目的と思われます。

こうすると、グローバル変数が使われていることが一目でわかり、またその変数名もわかるので、できるだけこの手法を使った方が良いかもしれません。



さてグローバル変数を使えば、なにも問題はないようにも見えますが、
ヘルプには、こう書かれています
一般的に、可能な限りグローバル変数の使用は避けるのが良いプログラミング法です。これにより、プロシージャの呼び出しに伴う悪影響が生じる可能性が少なくなります



----------------------------------------
<プロシージャの引数を使う>


プロシージャ名の後ろの( )は引数を指定するために使われる。
引数は変数宣言と同じようにでき、複数指定も可能である。
参照:オンラインヘルプ「プロシージャを定義する

global proc test1(int $value)
{
print $value;
}
// ***************

global proc test2()
{
int $x5;
$x5 = 9;

test1($x5);
}


この例では、test2()の中で使われた$x5変数の値をそのままtest1()プロシージャを実行するときに引数として渡しています。

上記のスクリプトを実行後、
test2
とタイプして実行すれば、答えの9が表示されます。




----------------------------------------
<変数を使わない>


これは正確には情報のやりとりではなく、各プロシージャから共用できるものを見つけるという考え方であり、発想の転換です。
変数を使わなければその落とし穴にはまることもありません。

実際には、ウインドウやコントロールの名前など、そのスクリプト内では共通しており、直接指定して使う事ができるものです。

しかしながら、ウインドウやコントロールを作成するとき、アサインをつかってその名前を変数に入れる方法になれきってしまうと、この落とし穴にはまってしまいます。
(参照:DigitalMatrix 「アサインとは」)


こういうときはあえて、変数を使用しない方法を考えてみれば、視野が広がります。
よくよく考えてみれば変数を使用しなくてもよいことはあります。

あるプロシージャーをウインドウ作成専用にして、他のプロシージャでそのウインドウを変更したいとする。
アサインを使って同一プロシージャ内で作業するには便利だが、これを他のプロシージャに使おうとすると、とたんにめんどくさい手続きが必要となる。

しかし、ウインドウやコントロールを作成するときに名前を指定するようにすれば、他のプロシージャ内で、その名前を使えばよいだけだ。 あえて変数をつかわなくてもよい。

フィールドの値などを取得するにはコントロールの名前が必要になる。そういうときに使えば、グローバル変数を使わずに簡単にすませることができる。

0 件のコメント:

コメントを投稿