- ベストアンサー
参照なバリアント
VB熟達者というよりは、VBマニアな方々に質問です。 Sub Hoge(A) A = 6 End Sub Sub Main() Dim N As Long Hoge N Debug.Print N End Sub このコードを実行して "6" が出力されるのは明白です。 Hogeはバリアントの参照を取るにも関わらず、LongのNを渡してそのNに6を入れてくれました。 これは、VBが引数を渡す時点で変数A用のメモリ領域をかってに確保し、Nという変数の参照型を作ったということの証拠になります。 実際、DLLでAPIを用意して、バリアント構造体のVarTypeを調べたところ、未知の16387という数値が現れました。 これは、MSDNライブラリを見たところ、VT_LONG Or VT_BYREFのようです。 このように、VBでも参照型は存在していますが、隠蔽されています。 そこで、参照型をもっと自由に使いたいと思い、参照型を作るAPIを作ってみました。 しかし、=演算子で代入しようとしたところ、参照が解除されて通常のバリアント型に戻ってしまいます。 ただし、もともとある変数の参照であるバリアント変数を別の変数の参照に変えたもののときは、参照先に代入してくれました。 どうやらVBはケチなようで、VBが内部で引数として作った参照変数以外は、参照している先に代入はしてくれないようです。 この障害を乗り越える方法を思いついた方、ぜひ教えてください。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
通常、VBでメソッドを呼び出すときは内部では DISPPARAMS構造体に引数をセットします。 この構造体の中では引数はVARIANTARGにセットされ、 VARIANTARGの内部で引数のポインタが保持されます。 つまり、VBでメソッドを呼び出すときは 内部的には常にVariant型で呼ばれていると考える事ができます。 Privateの関数を呼ぶときはそんな面倒くさい事をしないで Cと同じように呼んでいるかと考えていたのですが もし、ご質問されているような結果が出るのでしたら DISPPARAMSを使用しているのかもしれませんね。
その他の回答 (2)
- msystem
- ベストアンサー率42% (79/186)
APIを作るということの解決案にはなりませんが、補足から勝手になぜそのようにしたいかを推測しました。 >Dim A As Variant, B As Long >MakeRef A, B とし、Aを変更すればBも勝手に変わる、またはその逆をしたいのでしょうか? もしそうであるなら、やはりクラスを作成しするのがいいように思います。 Dim obj1 as Object Dim obj2 as Object Set obj1 = New ClassA Set obj2 = obj1 とすれば、大丈夫なような気がします。 勝手な予想で、でしゃばって申し訳ありません。
お礼
それは一応私も考えてみました。 しかし、やっぱり、LongやDoubleの参照を作りたいわけです。 LongやDoubleのポインタを取得して、参照/代入を行うクラスも作ってみました。 最後にはやっぱりVariant型を懲らしめてやりたい(?)のです。
- msystem
- ベストアンサー率42% (79/186)
あまり自信がないのですが・・・ >これは、VBが引数を渡す時点で変数A用のメモリ領域をかってに確保し、Nという変数の参照型を作ったということの証拠になります。 何をさして証拠といわれているのかちょっとわかりませんが、プロシージャの引数は、参照渡しがデフォルトであることはマニュアルに記載があります。(当然、値渡しもあります。) >参照型をもっと自由に使いたいと思い、参照型を作るAPIを作ってみました。 どのような処理をすることをしたいのかはっきりしませんが、VBの仕様でプロシージャの引数以外に参照値を渡す(代入する)ことはできないような気がします。 当然、=演算子で代入することは仕様上できないと思います。 ところで、「参照型を作るAPI」というのは、言語は何で作られたのでしょうか? VBで作るのであれば、クラスを作成し、クラス内で参照値を返すように見えるメソッドは作れるような気がしますが、VBは演算子のオーバーライドができないので、=演算子を使って操作できるようにはできないような気がします。 CやC++言語を使い、同じように作ることもできるような気はしますが、VB側で演算子のオーバーライドがやはりできないので、=演算子を使用することはできないと思います。
補足
関数はバリアント型の参照をほしがっているのに、Longの変数が渡せること自体が、C++から考えるとおかしなことだということです。 要は、VBでは、Cのように関数を呼び出すときに、スタックのpush、pop、callだけを行っているのではなく、mallocを使ったり、Variant構造体の内部をいじったりしているといいたいのです。 参照型をもっと自由に使いたいというのは、 Dim A As Variant, B As Long MakeRef A, B とすれば、AがBの参照になるような関数を作りたいと言うことです。 C++では次のようにすれば簡単ですが。 long B; long& A = B; ちなみに、APIを作る環境は、C++のWin32 DLLです。
お礼
ということは、その構造体内で宣言された変数しか、=は参照型として扱ってくれないということなのでしょうね。 実際、Variantの参照を取る関数に、Variantの変数を渡したとき、渡した側で調べたときと、関数内で調べたときと、変数のアドレスが違っていました。 DISPPARAMS構造体というのは、初めて聞いたのですが、これなら納得がいきます。 GetWindowsDirectoryAなどのAPIにBSTRを渡しているのに、ちゃんと文字列が得られるというのも、同時に納得がいきました。