Variant (VT_ARRAY) в .NET
От: MaxiMal_TSG Россия  
Дата: 22.09.10 04:49
Оценка:
Здравствуйте, не могу понять как передавать VARIANT из Com метода (ATL/C++) в C#.

Com метод ATL:

STDMETHODIMP COMCK::RetKosmoSystems(BSTR PathToKosmoFile, VARIANT* KosmoSystems)
    {
        CString Path , cs ;
        Path  = PathToKosmoFile;
        int RetVal;
        RetVal = this->KosmoExplorer.RetKosmoSystems(Path, KosmoSystems->parray );
        KosmoSystems->vt = VT_SAFEARRAY + VT_BSTR;
        if (RetVal <= 0)
                .....
        }


Клиентская сторона С#

            COMCKLib.ICOMClass m_CK = new COMCKLib.ICOMClass();
            Object obj = new object();
            m_CK.RetKosmoSystems(buttonEdit1.Text , ref obj);


При выполнении метода m_CK.RetKosmoSystems(buttonEdit1.Text , ref obj) возникает сообщение:

Additional Information: Обнаружено недопустимое значение типа VARIANT во время преобразования неуправляемого значения типа VARIANT в управляемый объект. Передача в CLR недопустимого значения типа VARIANT может вызвать неожиданные исключения, а также повреждение или потерю данных.

При нажатии continue выскакиевает исключение:
Exception: Данный метод возвратил тип Variant COM, который не совместим с Interop.
Method: RetKosmoSystems
Full name: COMCKLib.ICOMClass
Module: Interop.COMCKLib.dll

Ответы на форумах в основном сводятся к советам типа попробуй использовать тип Object или используй тип Object , а потом откасть его к тому что надо. Понятно такие ответы не удовлетворят , тем более что ошибка возникает раньше.
Re: Variant (VT_ARRAY) в .NET
От: Vi2 Удмуртия http://www.adem.ru
Дата: 22.09.10 05:13
Оценка:
Здравствуйте, MaxiMal_TSG, Вы писали:

MM_>... не могу понять как передавать VARIANT из Com метода (ATL/C++) в C#.

MM_>Com метод ATL:
MM_>STDMETHODIMP COMCK::RetKosmoSystems(BSTR PathToKosmoFile, VARIANT* KosmoSystems)
MM_>    {
MM_>        RetVal = this->KosmoExplorer.RetKosmoSystems(Path, KosmoSystems->parray );
MM_>        KosmoSystems->vt = VT_SAFEARRAY + VT_BSTR;

Вместо VT_SAFEARRAY используй VT_ARRAY, и не "+", а "|", т.е. KosmoSystems->vt = VT_ARRAY | VT_BSTR;
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: Стандартная задача
От: MaxiMal_TSG Россия  
Дата: 22.09.10 05:35
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Здравствуйте, MaxiMal_TSG, Вы писали:


MM_>>... не могу понять как передавать VARIANT из Com метода (ATL/C++) в C#.

MM_>>Com метод ATL:
Vi2>
MM_>>STDMETHODIMP COMCK::RetKosmoSystems(BSTR PathToKosmoFile, VARIANT* KosmoSystems)
MM_>>    {
MM_>>        RetVal = this->KosmoExplorer.RetKosmoSystems(Path, KosmoSystems->parray );
MM_>>        KosmoSystems->vt = VT_SAFEARRAY + VT_BSTR;
Vi2>

Vi2>Вместо VT_SAFEARRAY используй VT_ARRAY, и не "+", а "|", т.е. KosmoSystems->vt = VT_ARRAY | VT_BSTR;


почему, можно подробнее? Клиент на С++

        VARIANT vt;::VariantInit(&vt);
    _bstr_t bs = (const char*)csPath;
    if((m_bOneSubstMode && m_pSpace->raw_RetKosmoSubsts(bs,&vt)== S_OK) ||
        (!m_bOneSubstMode && m_pSpace->raw_RetKosmoSystems(bs,&vt)== S_OK))
            if(vt.vt == VT_BSTR+VT_SAFEARRAY)
            {

отлично отрабатывает. Так что уже работающую менять не очень хочется. Можно ли решить проблему чисто с шарповской стороны ? Если нет то это большой недостаток , возможно придется менять уже работающий код.
Re[3]: Стандартная задача
От: Vi2 Удмуртия http://www.adem.ru
Дата: 22.09.10 06:04
Оценка: 11 (2) +2
Здравствуйте, MaxiMal_TSG, Вы писали:

MM_>почему, можно подробнее? Клиент на С++


Цитата из файла WTYPES.H:

* VT_SAFEARRAY [T] (use VT_ARRAY in VARIANT)

VT_SAFEARRAY — это такая же полноправная константа как и VT_BSTR (VT_SAFEARRAY = 27, VT_BSTR = 8), т.е. они не могут работать совместно. Причём VT_BSTR+VT_SAFEARRAY = 27+8 = 35, а такого типа хранения в VARIANTе нет.

VT_SAFEARRAY используется только при описании типов в библиотек типов и показывает, что на этом уровне вложенности используется какой-то SAFEARRAY.

MM_>        VARIANT vt;::VariantInit(&vt);
MM_>    _bstr_t bs = (const char*)csPath;
MM_>    if((m_bOneSubstMode && m_pSpace->raw_RetKosmoSubsts(bs,&vt)== S_OK) ||
MM_>        (!m_bOneSubstMode && m_pSpace->raw_RetKosmoSystems(bs,&vt)== S_OK))
MM_>            if(vt.vt == VT_BSTR+VT_SAFEARRAY)
MM_>            {

MM_>отлично отрабатывает. Так что уже работающую менять не очень хочется. Можно ли решить проблему чисто с шарповской стороны ? Если нет то это большой недостаток , возможно придется менять уже работающий код.

Это происходит потому, что не задействован маршаллинг. Как только он появится, то появятся и проблемы в С++ тоже. Так что менять код придётся в любом случае, т.к. он не правильный с точки зрения СОМ.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Стандартная задача
От: MaxiMal_TSG Россия  
Дата: 22.09.10 06:53
Оценка:
Здравствуйте, Vi2, Вы писали:



Большое спасибо за пояснения.
Попробовал предлагаемый вариант , все сработало.
Понял , что грамотнее будет поменять код клиента на С++ .
Еще раз спасибо!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.