Есть COM объект, который юзается из C#. Нужно мне из него вернуть массив объектов IMyClass, вернее не сами объекты, а ссылки на них, физически они должны хоститься в моём COM-сервере. Как бы это грамотнее сделать? Я думаю юзать SAFEARRAY и VT_DISPATCH, только не совсем понятно, как их принимать в C#, и что при маршалинге будет...
Здравствуйте, amOK, Вы писали:
OK>Есть COM объект, который юзается из C#. Нужно мне из него вернуть массив объектов IMyClass, вернее не сами объекты, а ссылки на них, физически они должны хоститься в моём COM-сервере. Как бы это грамотнее сделать? Я думаю юзать SAFEARRAY и VT_DISPATCH, только не совсем понятно, как их принимать в C#, и что
при маршалинге будет...
Здравствуйте, Plutonia Experiment, Вы писали:
PE>Здравствуйте, amOK, Вы писали:
OK>>Есть COM объект, который юзается из C#. Нужно мне из него вернуть массив объектов IMyClass, вернее не сами объекты, а ссылки на них, физически они должны хоститься в моём COM-сервере. Как бы это грамотнее сделать? Я думаю юзать SAFEARRAY и VT_DISPATCH, только не совсем понятно, как их принимать в C#, и что PE>при маршалинге будет...
PE>Можно вот так.
PE>
PE>А вообще есть панацея. Пишешь на шарпе класслайбари а в ней такие интрефейсы, как тебе надо. Потом регистришь regasm /tlb и смотришь, что в tlb будет.
PE>Выдираешь IDL для интерфейса и имплементишь его у себя на С++.
У меня возникла такая проблема: я объявляю в idl тип как SAFEARRAY(IDispatch*), или SAFEARRAY(IMyClass*). Но в С++ при создании этого массива с помощью SafeArrayCreateVectorEx(VT_DISPATCH, ...) и при попытке туда чего-нить запихнуть SafeArrayPutElement(...) летит исключение. Если же я создаю SafeArrayCreateVectorEx(VT_VARIANT, ...), то массив нормально заполняется, но потом шарп, ругается, что не правильный тип.
Я попробовал объявить SAFEARRAY(VARIANT) и получил Array из __ComObject, но как их привести к IMyClass я не знаю ????
Здравствуйте, amOK, Вы писали:
OK> Я попробовал объявить SAFEARRAY(VARIANT) и получил Array из __ComObject, но как их привести к IMyClass я не знаю ????
1. Создаешь проект ClassLibrary
2. Пишешь такой интерфейс, который хочешь видеть в дотнете
3. Экспортируешь в COM
4. Смотришь, что получилось
5. Вставляешь себе ва проект на С++
Здравствуйте, Plutonia Experiment, Вы писали:
PE>Здравствуйте, amOK, Вы писали:
OK>> Я попробовал объявить SAFEARRAY(VARIANT) и получил Array из __ComObject, но как их привести к IMyClass я не знаю ????
PE>
PE>Повторяю еще раз.
PE>1. Создаешь проект ClassLibrary PE>2. Пишешь такой интерфейс, который хочешь видеть в дотнете PE>3. Экспортируешь в COM PE>4. Смотришь, что получилось PE>5. Вставляешь себе ва проект на С++
Собственно, я это делал, он мне сказал SAFEAARRAY(IMyClass*). Но я писал, что не могу создать такой массив в С++.
Здравствуйте, Plutonia Experiment, Вы писали:
PE>Здравствуйте, amOK, Вы писали:
OK>>Собственно, я это делал, он мне сказал SAFEAARRAY(IMyClass*). Но я писал, что не могу создать такой массив в С++.
PE>В с++ это будет просто SAFEARRAY. Получи IDL файл и напусти на него MIDL. Там посмотришь, в каком виде это будет в С++.
PE>Можно написать мекого клиента на С++, что бы посмотреть, как к тебе это приходит со стороны дотнет. PE>А потом сделаешь тож самое, только на с++.
Дык собственно в С++ это будет в виде SAFEARRAY ** pArray. В том то и весь затык тут, что не понятно, как его правильно сделать, чтобы и С++ и С# поняли!
Здравствуйте, Plutonia Experiment, Вы писали:
PE>Можно написать мекого клиента на С++, что бы посмотреть, как к тебе это приходит со стороны дотнет. PE>А потом сделаешь тож самое, только на с++.
Я так и сделал.
Приходит Сейфаррей с таким флагом FADF_UNKNOWN | FADF_HAVEIID
Все пучком
Что бы создать такой нужно прочитать это
An array that has an IID identifying interface. When set there will be a guid at negative offset 16 in the safearray descriptor. Flag is set only when FADF_DISPATCH or FADF_UNKNOWN is also set.
Здравствуйте, amOK, Вы писали:
OK>Дык собственно в С++ это будет в виде SAFEARRAY ** pArray. В том то и весь затык тут, что не понятно, как его правильно сделать, чтобы и С++ и С# поняли!
Здравствуйте, Plutonia Experiment, Вы писали:
PE>Приходит Сейфаррей с таким флагом FADF_UNKNOWN | FADF_HAVEIID PE>Все пучком
PE>Что бы создать такой нужно прочитать это
PE>
PE>An array that has an IID identifying interface. When set there will be a guid at negative offset 16 in the safearray descriptor. Flag is set only when FADF_DISPATCH or FADF_UNKNOWN is also set.
Здравствуйте, Plutonia Experiment, Вы писали:
PE>Здравствуйте, amOK, Вы писали:
OK>>Дык собственно в С++ это будет в виде SAFEARRAY ** pArray. В том то и весь затык тут, что не понятно, как его правильно сделать, чтобы и С++ и С# поняли!
PE>Сам сейфаррей не знаешь, чем заполнить ?
Тип того. Короче такой код:
CComObject<CTTHelperClientItem> *pClient1 = NULL;
hr = CComObject<CTTHelperClientItem>::CreateInstance(&pClient1);
if (FAILED(hr))
return hr;
CComObject<CTTHelperClientItem> *pClient2 = NULL;
hr = CComObject<CTTHelperClientItem>::CreateInstance(&pClient2);
if (FAILED(hr))
return hr;
SAFEARRAY * sa;
sa = SafeArrayCreateVectorEx(VT_DISPATCH, 1, 2, (void**)&__uuidof(ICTTHelperItem));
long index = 1;
VARIANT var;
V_VT(&var) = VT_DISPATCH;
pClient1->QueryInterface(IID_ICTTHelperItem, (void **)&V_DISPATCH(&var));
SafeArrayPutElement(sa, &index, &var);
index ++;
pClient2->QueryInterface(IID_ICTTHelperItem, (void **)&V_DISPATCH(&var));
SafeArrayPutElement(sa, &index, &var);
ICTTHelperClientItem наследуется от ICTTHelperItem.
Вот на первом вызове SafeArrayPutElement летит исключение. Если поставить в SafeArrayCreateVectorEx VT_VARIANT, то тут всё нормально, но в С# не хочет приводится к нужному интерфейсу.
Здравствуйте, amOK, Вы писали:
OK>Тип того. Короче такой код:
OK>
OK>SAFEARRAY * sa;
OK>sa = SafeArrayCreateVectorEx(VT_DISPATCH, 1, 2, (void**)&__uuidof(ICTTHelperItem));
А зачем вектор ?
Нужно создать этой фунцыей SafeArrayAllocDescriptor
Потом указать размерность
Потом сделать SafeArrayAllocData
Потом SafeArraySetIID
И в конце делаешь
pClient2->QueryInterface(IID_ICTTHelperItem, (void **)&V_DISPATCH(&var));
SafeArrayPutElement(sa, &index, &var);
OK>