どのようにしてLPSAFEARRAY出力パラメータにローカルCComSafeArrayを返すのですか?

StackOverflow https://stackoverflow.com/questions/1778491

  •  21-09-2019
  •  | 
  •  

質問

私は、パラメータアウトLPSAFEARRAY*経由のSafeArrayを返すべきCOM機能を持っています。 関数は、ATLのCComSafeArrayテンプレートクラスを使用してのSafeArrayを作成します。 私の素朴な実装の用途は、出力パラメータにローカル変数から所有権を移動するためにCComSafeArray<T>::Detach()ます:

void foo(LPSAFEARRAY* psa)
{
    CComSafeArray<VARIANT> ret;
    ret.Add(CComVariant(42));
    *psa = ret.Detach();
}

int main()
{
    CComSafeArray<VARIANT> sa;
    foo(sa.GetSafeArrayPtr());

    std::cout << sa[0].lVal << std::endl;
}

の問題は、のSafeArray(この場合のメインCComSafeArray::Detach())の新しい所有者が破壊されたときにロックがゼロでないとUnlockはA(このリードsaとのSafeArrayのロックを解除することができないようにそのDestroyが実行E_UNEXPECTED動作でありますSafeArrayので、メモリリーク)が割り当てを解除されていない。

はCOMメソッドの境界を通してCComSafeArraysの間の転送の所有権への正しい方法は何ですか?

<時間>

編集の単一の答えはこれまでのところ、エラーがクライアント側(main)といないサーバ側から(foo)上にあるようですが、私はそのCComSafeArrayを信じるのは難しいそれを見つけることから、この些細なユースケースのために設計されていなかったが、CComSafeArrayにCOMメソッドの外のSafeArrayを取得するためのエレガントな方法が存在しなければならない。

役に立ちましたか?

解決

問題は、あなたが直接受信CComSafeArrayの内部ポインタを設定することです。 Attach()に既存のSAFEARRAYを添付するCComSafeArrayメソッドを使用します:

LPSAFEARRAY ar;
foo(&ar);
CComSafeArray<VARIANT> sa;
sa.Attach(ar);

他のヒント

ただ、マークの答えが正しいものであることを確認します。 RAIIラッパーできないCOMの境界を越えて仕事ます。

ポストされたメソッドの実装が正しくない、あなたは、呼び出し元が有効なSAFEARRAYを供給しようとしていることを前提とすることはできません。ただ、[実行]オートメーションにおける有効な属性ではありません、それは[retvalのアウト]または[アウト、中]のいずれかでなければなりません。それは次のようになります[アウト、RETVAL]、である場合、この方法は、最初から新しい配列を作成する必要があります。それは[アウト、中]であれば、それは予想される配列型と一致して、新しいものを作成しない場合、メソッドは、渡された配列破壊する必要があります。

私は、このようなユースケースを許可する意図はどこになかったことを推測すると思います。おそらくそれはCComVariantCComPtr :)

書いた同じ開発者ではありませんでした

私は、大きな目標として、そのCComSafeArrayの作者とみなさ値のセマンティクスを信じています。アタッチ/デタッチは、単に「ボーナス」機能かもしれません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top