在用C++编写的COM客户端中引发异常的Null返回值

本文关键字:异常 返回值 Null 客户端 C++ COM 在用 | 更新日期: 2023-09-27 18:29:40

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

除了当我的C#方法通过COM向C++返回null时,一切都很好。在C++中抛出一个excpetion,上面写着

"调试断言失败!"。。。。。atlsafe.h 235号线表达式psaSrc!=无效的

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

例如

CComSafeArray项实体=objController1->ListItems(sPath);

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

请有人提出解决方案。

谢谢,Gagan

在用C++编写的COM客户端中引发异常的Null返回值

它一定是代码中没有显示的部分。这对我有效:

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++调用GetStringArrayGetStringArray2

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,它在设计上不需要NULL SAFEARRAY:

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
}

COM中的返回值是保留的,用于将异常传递给不同的模块。要获得一个真实的返回值,可以在函数中添加一个out参数,并将其用作返回值。我以为C#互操作系统已经为您完成了这项工作,但似乎您需要手动完成。