なぜそれがIDLインタフェースの*最後*に新しいイベントを追加する必要がありますか?
質問
私は、既存のCOM / IDLインタフェースに新しいイベントを追加するとき、彼らはインターフェイスの最後に追加されていない限り、私は時々奇妙な問題に遭遇していることを発見した。
たとえば、私は次のインタフェースを持っていると言います
interface IMyEvents
{
HRESULT FooCallback(
[in] long MyParam1,
[in] long MyParam2,
[in] long MyParam3);
HRESULT BarCallback(
[in] long MyParam1,
[in] BSTR MyParam2,
[in] BSTR MyParam3);
};
今度は、私は新しいコールバックイベント、NewCallback
を追加したいとしましょう。私はこのようにそれを追加した場合、イベントがCOM渡って発射されたとき、私はすべての問題を持っていない傾向がある。
interface IMyEvents
{
HRESULT FooCallback(
[in] long MyParam1,
[in] long MyParam2,
[in] long MyParam3);
HRESULT BarCallback(
[in] long MyParam1,
[in] BSTR MyParam2,
[in] BSTR MyParam3);
/* New event added to the end */
HRESULT NewCallback(
[in] BSTR MyParam1,
[in] BSTR MyParam2,
[in] BSTR MyParam3);
};
しかし、私はこのようにそれを追加した場合、私はイベントが発生している問題のすべての種類(例えば、バッファオーバーラン)に実行することができます。
interface IMyEvents
{
HRESULT FooCallback(
[in] long MyParam1,
[in] long MyParam2,
[in] long MyParam3);
/* New event added to the middle */
HRESULT NewCallback(
[in] BSTR MyParam1,
[in] BSTR MyParam2,
[in] BSTR MyParam3);
HRESULT BarCallback(
[in] long MyParam1,
[in] BSTR MyParam2,
[in] BSTR MyParam3);
};
私はそれがDLLエントリポイント、アドレスオフセット、または類似した何かとは何かを持って推測しています。それともそれは私が再構築されていないため、適切なものだし、最後にそれを追加すると、それは全くの幸運で作業することができます。
誰もが、この動作を説明することはできますか?
解決
あなたは、既存のCOMインターフェイスを変更することになっていません。変更してコンパイルされていないクライアントは、それを認識していないと、彼らは変更の前に行っていたとして呼び出してまいります。
結果は、既存のクライアントが長整数でBarCallbackを呼び出すことで、これに代えて、長整数がBSTRであると考えてNewCallbackを取得します。結果はしばしばunpleasentされます。
あなたは最後に新しい機能を追加することで同様の問題を取得します。古いCOMオブジェクトが実装された新しい機能を持っていない、あなたはそれを呼び出すようにしようとすると、可能性だけでクラッシュしてしまいます。
古いインタフェースを使用して野生に既存のクライアントを持っていない場合は、しかし、ちょうどあなたがすべての登録を解除して、生成されたオブジェクトは、クライアントとプロキシとスタブを置き換えることを確認してください。
他のヒント
私はそれが最後にコードを追加することとは何かを持っているとは思わない。
私は、インターフェイスファイルの半ばに機能を追加することを覚えています。
しかし、いつでもあなたはそれを修正し、あなたはDLLの登録を解除して、もう一度、すべてのファイルを再生成することを確認してください。 (以前の記事で述べたように) 実行時にこのようなものをデバッグすることは難しいですので、すべての段階で正確ます。