2

COMクラスを呼び出すC#Winformsアプリケーションがあります。Visual Studioを使用してデバッグする場合、C ++コードにステップインしてS_OKを返しますが、関数が戻るとVisual Studioがハングし、アプリケーションがクラッシュします。プログラムの実行を停止するには、VSプロセスでプロセスを終了する必要があります。Visual Studioの外部でアプリを実行すると、アプリケーションがクラッシュします。

すべてが正常に機能していて、この問題を引き起こすために何をしたのかわかりません。

どんな助けでも大歓迎です。ありがとう

Sj

これはインターフェース定義です

typedef struct
{
    long    ExpiryData
    BSTR    IssuedBy;
} LicenceData;

[
    object,
    uuid (5A734F95-EABE-440B-8B7E-0F73538A24AC), 
    pointer_default(unique),
    helpstring("ILicenceReader Interface"),
]
interface ILicenceReader : IDispatch
{
    HRESULT ReadLicenceFile ([in, out]LicenceData* plicenceData, LPCTSTR filePath);
};

[
    uuid(C2833A21-6586-4648-ABC8-D42BC3225699)      
]
coclass LicenceReader
{
    [default] interface ILicenceReader;
};

COM dllを参照し、VSが相互運用機能とc#アプリケーションでの使用法を生成できるようにしました。

LicenceData data = new LicenceData();

ILicenceReader reader = new LicenceReader();

reader.ReadLicenceFile(ref data, filePath);

ご協力いただきありがとうございます。

4

1 に答える 1

0

COMサブシステムが、スタックに割り当てられたBSTR、またはスタック上のスマートポインターで割り当てられたBSTRをアンマーシャリングしようとしていることは間違いありません。

BSTRはSysAllocStringで割り当てる必要があります。これによる結果は、スタック上になく、誤って解放しようとするものがないため、そのまま返すことができます。

CComBSTRや_bstr_tなどのスマートポインターBSTRクラスを使用する場合は、Detachを介してIssuedByメンバーを設定する必要があります。CComBSTR :: Detach()は、BSTRへのポインターを返し、CComBSTRのローカルインスタンスがスコープ外になったときにそれを解放しようとはしません。

plicenceData->IssuedBy = CComBSTR("Some Dude").Detach();

もう1つの可能性は、COMクラス内でplicenceData = new plicenceDataのようなことを実行して、渡されたインスタンスを上書きしようとすることです。これは機能しません。

結局、COM関数が終了して返された後に失敗する唯一の理由は、マーシャリングの問題が原因です。これは、C#コードと呼び出されたC ++の間のレイヤーであり、アパートを越えてデータを変換し、場合によっては境界を処理しようとします。マーシャリングがその仕事を行えるようにするには、レターのCOMルールに従っていることを確認する必要があります。

したがって、すべてのポインタを再確認してください。それらはスタック上にありますか、それともヒープ上にありますか?それらはヒープ上にある必要があります。すべてのBSTRは適切に割り当てられていますか?通常、スマートBSTRクラスを使用すると非常に役立ちますが、生のメンバーを返すことはできないことに注意してください。これらのクラスは、使用が予想されるとおりに使用してください。

于 2012-05-23T00:11:39.057 に答える