1

C# dll の COM ラッパーを作成し、この COM コンポーネントを C++ で使用して、C# dll のメソッドを呼び出します。

私のC#メソッドがCOMからC ++にnullを返す場合を除いて、すべて正常に機能しています。C++ で次のような例外がスローされます。

「デバッグ アサーションに失敗しました!」..... atlsafe.h 行 235 式 psaSrc != null.

このエラーを回避し、戻り値の型で null 値を受け入れるにはどうすればよいですか。

たとえば。

CComSafeArray itemEntities = objController1->ListItems(sPath);

ListItems メソッドが null を返す場合、システムはエラーをスローすべきではありません。代わりに、itemEntities を st から NULL にする必要があります。

誰かが解決策を提案してください。

ありがとう、ガガン

4

2 に答える 2

0

COM の戻り値は、異なるモジュールに例外を渡すために予約されています。実際の戻り値を取得するには、out パラメータを関数に追加し、これを戻り値として使用できます。C# COM Interop が既にこれを行っていると思っていましたが、手動で行う必要があるようです。

于 2013-08-31T06:06:20.560 に答える
0

それは、あなたが示していないコードの一部にあるものでなければなりません。これは私のために働く:

C# クラス:

[ComVisible(true)]
[Guid("BE55747F-FEA9-4C1F-A103-32A00B162DF0")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Test
{
    //[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
    public string[] GetStringArray()
    {
        var a = new string[3];
        a[0] = "string0";
        a[1] = null;
        a[2] = "string2";
        return a;
    }

    public string[] GetStringArray2()
    {
        return null;
    }
}

GetStringArrayおよびGetStringArray2C++ からの呼び出し:

SAFEARRAY* pSA = NULL;
testObject->GetStringArray(&pSA);
printf("str0: %ls\n", ((BSTR*)(pSA->pvData))[0]);
printf("ptr1: %x\n", ((BSTR*)(pSA->pvData))[1]);
printf("str2: %ls\n", ((BSTR*)(pSA->pvData))[2]);

SAFEARRAY* pSA2 = NULL;
testObject->GetStringArray2(&pSA2);
printf("pSA2: %x\n", pSA2);

走る:

str0: string0
ptr1: 0
str2: string2
pSA2: 0

SAFEARRAY(VT_BSTR)配列はデフォルトでマーシャリングされるため、配列のマーシャリング方法 (コメントアウトされた行) を指定する必要はありませんでした。

EDITED:問題がどこにあるかがわかると思います。設計上、SAFEARRAY をCComSafeArray想定していないATL を使用しています。NULL

CComSafeArray(_In_ const SAFEARRAY *psaSrc) : m_psa(NULL)
{
    ATLASSERT(psaSrc != NULL);
    HRESULT hRes = CopyFrom(psaSrc);
    if (FAILED(hRes))
        AtlThrow(hRes);
}

次のようにコードを変更する必要があります。

CComSafeArray<BSTR> itemEntities;
SAFEARRAY* pItemEntities = objController1->ListItems(sPath);
if (NULL != pItemEntities)
    itemEntities.Attach(pItemEntities);

m_psaまたは、直接割り当てます。

CComSafeArray<BSTR> itemEntities
itemEntities.m_psa = objController1->ListItems(sPath);
if (!itemEntities)
{
    // NULL returned
}
于 2013-09-03T01:07:42.790 に答える