C # — исключение пустого возвращаемого значения в COM-клиенте, написанном в переполнении стека

Я сделал оболочку COM над C # dll и использую этот компонент COM в C ++ для вызова методов в C # dll.

Все работает нормально, кроме случаев, когда мой метод C # возвращает ноль через COM в C ++.
в C ++ создается исключение, которое говорит

«Утверждение отладки не удалось!» ….. atlsafe.h Строка 235
Выражение psaSrc! = Null.

Как избежать этой ошибки и принять нулевое значение в типе возвращаемого значения.

например,

CComSafeArray itemEntities = objController1-> ListItems (sPath);

Когда метод ListItems возвращает ноль, система не должна выдавать ошибку.
Вместо этого itemEntities должен быть равен NULL.

Пожалуйста, кто-нибудь предложит решение.

Спасибо,
Gagan

1

Решение

Это должно быть что-то в той части вашего кода, которую вы не показывали.
Это работает для меня:

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 а также GetStringArray2 из C ++:

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 БЕЗОПАСНОСТЬ по дизайну:

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

Другие решения

Возвращаемое значение в COM зарезервировано для передачи исключений в разные модули. Чтобы получить реальное возвращаемое значение, вы можете добавить параметр out в свою функцию и использовать его в качестве возвращаемого значения. Я думал, что C # COM Interop уже сделает это за вас, но кажется, что вам нужно сделать это вручную.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector