1

我在 C# dll 上制作了一个 COM 包装器,并在 C++ 中使用这个 COM 组件来调用 C# dll 中的方法。

一切正常,除非我的 C# 方法通过 COM 将 null 返回到 C++。在 C++ 中抛出了一个异常,上面写着

“调试断言失败!” ..... atlsafe.h 第 235 行表达式 psaSrc != null。

如何避免此错误并在返回类型中接受空值。

例如。

CComSafeArray itemEntities = objController1->ListItems(sPath);

当 ListItems 方法返回 null 时,系统不应抛出错误。相反 itemEntities 应该是 st 为 NULL。

请有人提出解决方案。

谢谢,加根

4

2 回答 2

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;
    }
}

从 C++调用GetStringArray和:GetStringArray2

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)默认情况下它会被编组。

编辑:我想我知道问题出在哪里。您正在使用 ATL CComSafeArray,它不期望NULLSAFEARRAY 的设计:

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 回答
0

COM 中的返回值保留用于将异常传递给不同的模块。要获得真正的返回值,您可以在函数中添加一个 out 参数并将其用作返回值。我认为 C# COM Interop 已经为您执行此操作,但您似乎需要手动执行此操作。

于 2013-08-31T06:06:20.560 回答