« [Ruby] unicorn | トップページ | [Ruby] pr-win32ole その3 »

2009年9月 5日 (土)

[Ruby] pr-win32ole その2

期待してよいのはポインタの4バイトだけと artonさんからコメントをいただいた。

ということは、私は完璧にずっと勘違いしていたということになります。 で、「困ったときのPerl」の格言(←嘘)に従い、Perlはどうしているんだろうなと思って OLE.xs を調べたら、 pVarResult に対しては全く何もしてなかった。

ということは、私が勝手に勘違いして、勝手にpVarResultの処理を独自に追加したんだろうな。きっと。 pVarResult は、[out] なので、Win32OLE 側(呼び出し先)でメモリーを確保して返してあげればいいのか。 メモリーの解放は、OLEサーバ側(呼び出し元)でやってくれるので、気にすることはないのか。

念のため、pVarResultに値を設定しないことにしたら動きがどうなるか質問してみた(ruby-talk:345711)ら、 エラーは消えたけど、エラーメッセージも何も表示せずにクラッシュするようになったらしい(ruby-talk:345759)。

ということは、OLE.xs みたいに何もしないという訳にもいかんのか。

OLEサーバは、pVarResultにNULL以外を指定してWin32OLEを呼び出していて、 呼び出した後、OLEサーバは、何か値が設定されているだろうと期待して、pVarResultを参照したところクラッシュしたということか。

結局、どんなイベントを起こすとそうなるか知りたかったので、もう少しイベントの情報を教えてくれとお願いしてみた。

pr-win32ole はこんな感じにすれば動くのかな。

if pvarResult
  v = 0.chr * 16
  VariantInit(v)
  WIN32OLE.ole_val2variant(result,v)
  return VariantCopyInd(pvarResult, v)
end

|

« [Ruby] unicorn | トップページ | [Ruby] pr-win32ole その3 »

コメント

すみません。前の書き込みは[out, retval]BSTR* ppResultのようなものを想定していました。
[out, retval]VARIANT* pResult であれば、呼ばれた側は、if (pResult) { VariantInit(pResult); pResult->vt = VT_xxx... ; } が正しいです。
VariantCopyIndについては、「This function frees existing content of the destination variant (MSDN)」なので、outなVariantには直接、利用できません。最初にVariantInitでVT_EMPTYに設定する必要があります。

投稿: arton | 2009年9月 5日 (土) 16時33分

正直なところ、VariantInit以外のVariantが付くWin32 APIは、メモリーの扱いが不統一で危険なので、常にMSDNでメモリ操作について調べて利用するか、さもなければ直接vtやbstrValのようなメンバを操作するほうが良いと思います。
上の例では、VariantCopyIndの第2引数に与えているvにBSTRやIDispatchのようなメモリアロケーションが必要なオブジェクトが格納されていると、そのポインタをコピーするのか、再アロケート(あるいは再QIで参照カウンタを進める)かAPIドキュメントからは見えません(おそらくVB用にディープコピーすると思いますが記述されていないので想像でしかない)。したがってリークの可能性もあれば、逆に解放済みオブジェクトを参照する可能性もあります。

投稿: arton | 2009年9月 5日 (土) 16時40分

いやぁ、それにしてもVariantCopy一族は難しいですね。
VariantCopyであれば、結構、詳細までメモリルールを書いてあるんですが、VariantCopyIndは、CE版のAPI説明にデスティネーションのメモリ解放までは書いてありますが、ソースの扱いについては書いていないし。デリファレンスした結果でVariantCopyを内部的に呼ぶのであればディープコピー、そうでなければVariantCopyルールに従って、デリファレンスした場合はシャロウコピーで直接ポインタの場合はディープコピーということになりそうです。

投稿: arton | 2009年9月 5日 (土) 16時58分

いろいろありがとうございます。

とりあえず、私の認識は間違ってはいなかったということですね。
安心しました。

投稿: suke | 2009年9月 5日 (土) 17時22分

この記事へのコメントは終了しました。

トラックバック


この記事へのトラックバック一覧です: [Ruby] pr-win32ole その2:

« [Ruby] unicorn | トップページ | [Ruby] pr-win32ole その3 »