Как передать массив объектов в виде VARIANT
От: Аноним  
Дата: 01.04.04 15:26
Оценка:
Возникла острая необходимость написать небольшое приложение под AutoCAD с использованием OLE Automation. Документация по всему этому есть только для VBA, а я пишу на С++. В один из методов (штриховка контура) требуется передавать массив объектов, которые составляют контур в AutoCAD. Как это сделать на VBA описано в Help. Однако на основе этой информации я не понял, как это сделать на С++. Метод, сгенерированный в качестве обертки из TypeLibrary требует массив объектов в виде tagVARIANT. Пробовал множество различных способов (формировал SAFEARRAY напрямую из указателей на интерфейсы контуров, из указателей IDispatch контуров и др.), все ведут либо к появлению ошибки: "Invalid object array", либо к Access Violation по адресу 00000000.

Уже второй день бьюсь. Помогите, пожалуйста.
Re: Как передать массив объектов в виде VARIANT
От: Plutonia Experiment Беларусь http://blogs.rsdn.org/ikemefula
Дата: 01.04.04 15:32
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Возникла острая необходимость написать небольшое приложение под AutoCAD с использованием OLE Automation. Документация по всему этому есть только для VBA, а я пишу на С++. В один из методов (штриховка контура) требуется передавать массив объектов, которые составляют контур в AutoCAD. Как это сделать на VBA описано в Help. Однако на основе этой информации я не понял, как это сделать на С++. Метод, сгенерированный в качестве обертки из TypeLibrary требует массив объектов в виде tagVARIANT. Пробовал множество различных способов (формировал SAFEARRAY напрямую из указателей на интерфейсы контуров, из указателей IDispatch контуров и др.), все ведут либо к появлению ошибки: "Invalid object array", либо к Access Violation по адресу 00000000.


Покажи, как ты это далал. Непонятно, какая именно сигнатура тебе нужна
Re[2]: Как передать массив объектов в виде VARIANT
От: Аноним  
Дата: 01.04.04 16:39
Оценка:
Здравствуйте, Plutonia Experiment, Вы писали:


PE>Покажи, как ты это далал. Непонятно, какая именно сигнатура тебе нужна


Штриховка в AutoCAD создается последовательным вызовом двух методов:
методом добавления объекта Hatch и методом добавления контура к Hatch.

Вот пример на VBA из Help'а:


Sub Example_AppendOuterLoop()
    ' This example creates an associative hatch in model space.
    
    Dim hatchObj As AcadHatch
    Dim patternName As String
    Dim PatternType As Long
    Dim bAssociativity As Boolean
    
    ' Define the hatch
    patternName = "ANSI31"
    PatternType = 0
    bAssociativity = True
    
    ' Create the associative Hatch object
    Set hatchObj = ThisDrawing.ModelSpace.AddHatch(PatternType, patternName, bAssociativity)
    
    ' Create the outer loop for the hatch.
    ' An arc and a line are used to create a closed loop.
    Dim outerLoop(0 To 1) As AcadEntity
    Dim center(0 To 2) As Double
    Dim radius As Double
    Dim startAngle As Double
    Dim endAngle As Double
    center(0) = 5: center(1) = 3: center(2) = 0
    radius = 1
    startAngle = 0
    endAngle = 3.141592
    Set outerLoop(0) = ThisDrawing.ModelSpace.AddArc(center, radius, startAngle, endAngle)
    Set outerLoop(1) = ThisDrawing.ModelSpace.AddLine(outerLoop(0).startPoint, outerLoop(0).endPoint)
        
    ' Append the outer loop to the hatch object, and display the hatch
    hatchObj.AppendOuterLoop (outerLoop)
    hatchObj.Evaluate
    ZoomAll
    
End Sub



На C++ Builder обертка метода AppendOuterLoop выглядит так:

  // [14] Append loops to the hatch
  virtual HRESULT STDMETHODCALLTYPE AppendOuterLoop(VARIANT ObjectArray/*[in]*/) = 0;


Мне непонятно, как сформировать этот самый ObjectArray, чтобы он верно воспринимался.
Для начала я пытался передать массив объектов длиной 1, чтобы проверить, как это работает.
Делал это следующим образом:

 HRESULT hr;
 IAcadHatchPtr iHatch; //смарт-указатель, порожденный TComInterface

 //создаю объект Hatch, все работает верно
 hr = iModelSpace->AddHatch(acHatchPatternTypePreDefined,WideString("ANSI31"),0,&iHatch);
 if (FAILED(hr)) return;

 //пытаюсь сформировать массив
 Variant VarArr[1];
 VarArr[0] = (IAcadObject*)Contur; //Contur - объект типа IAcadPolylinePtr (смарт-указатель на полилинию)

 //формирую массив SAFEARRAY размером 1 на основе массива Variant и передаю в метод добавления контура
 //метод возвращает код ошибки, которому соответсвует сообщение "Invalid object Array"
 hr = iHatch->AppendOuterLoop(VarArrayOf(VarArr,0));
 if (FAILED(hr)) return; //выход по ошибке



Я пробовал формировать массив еще и другими способами, выполянл различные приведения типов и др.
Все попытки вели к одному из двух результатов, либо "Invalid object Array",
либо Access Violation at address 00000000 (или 00000001).

Мне поможет любая подсказка, даже без использования оберток C++ Builder. Главное, чтобы работало.
Re[3]: Как передать массив объектов в виде VARIANT
От: Plutonia Experiment Беларусь http://blogs.rsdn.org/ikemefula
Дата: 02.04.04 07:16
Оценка:
Здравствуйте, Аноним, Вы писали:

А>
А>  // [14] Append loops to the hatch
А>  virtual HRESULT STDMETHODCALLTYPE AppendOuterLoop(VARIANT ObjectArray/*[in]*/) = 0;
А>


А>Делал это следующим образом:


А>
А> Variant VarArr[1];
А> VarArr[0] = (IAcadObject*)Contur; //Contur - объект типа IAcadPolylinePtr (смарт-указатель на полилинию)
А>


Значитца так

Вот как создается массив строк.
Это на студии 7.0. Для Билдера не знаю, как это сделать.

Сейчас не могу, попозже если что, накидаю пример на чистом АПИ.

Вот здес кое что похожее
http://www.rsdn.ru/Forum/Message.aspx?mid=583447#583447
Автор: amOK
Дата: 25.03.04


Вобщем если нужен пример работающий, отпиши сюда или на почту, что в профайле.

STDMETHODIMP CArrayTest::ArrayTest(VARIANT* vararray)
{
    // TODO: Add your implementation code here
    CComSafeArray<BSTR> arr;

    arr.Add(::SysAllocString(L"1"));
    arr.Add(::SysAllocString(L"2"));
    arr.Add(::SysAllocString(L"3"));
    arr.Add(::SysAllocString(L"4"));

    CComVariant ret(arr);

    ret.Detach(vararray);
  
    arr.Detach();
    return S_OK;
}
Re[3]: Как передать массив объектов в виде VARIANT
От: Vi2 Удмуртия http://www.adem.ru
Дата: 02.04.04 09:08
Оценка:
Здравствуйте, Аноним, Вы писали:

А>    Dim outerLoop(0 To 1) As AcadEntity

А>    Set outerLoop(0) = ThisDrawing.ModelSpace.AddArc(center, radius, startAngle, endAngle)
А>    Set outerLoop(1) = ThisDrawing.ModelSpace.AddLine(outerLoop(0).startPoint, outerLoop(0).endPoint)
        
А>    ' Append the outer loop to the hatch object, and display the hatch
А>    hatchObj.AppendOuterLoop (outerLoop)

outerLoop — это SAFEARRAY(IDispatch*), а не SAFEARRAY(VARIANT), который передаешь ты.

Однако, скорее всего, одного SAFEARRAY(IDispatch*) будет недостаточно, так как обращение будет идти к vtable элементов массива, так что нужно использовать SafeArrayCreateEx с дополнительными фичами:
sa = SafeArrayCreateEx( VT_DISPATCH, 1, & sabound, & IID_IAcadEntity );
sa = SafeArrayCreateEx( VT_DISPATCH | FADF_HAVEIID, 1, & sabound, & IID_IAcadEntity );

Я не знаю, какая строчка будет правильной — с или без FADF_HAVEIID.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Как передать массив объектов в виде VARIANT
От: Plutonia Experiment Беларусь http://blogs.rsdn.org/ikemefula
Дата: 02.04.04 09:57
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Однако, скорее всего, одного SAFEARRAY(IDispatch*) будет недостаточно, так как обращение будет идти к vtable элементов массива, так что нужно использовать SafeArrayCreateEx с дополнительными фичами:

Vi2>
Vi2>sa = SafeArrayCreateEx( VT_DISPATCH, 1, & sabound, & IID_IAcadEntity );
Vi2>sa = SafeArrayCreateEx( VT_DISPATCH | FADF_HAVEIID, 1, & sabound, & IID_IAcadEntity );
Vi2>

Vi2>Я не знаю, какая строчка будет правильной — с или без FADF_HAVEIID.


FADF_HAVEIID нужно, если передаешь IID. Т.е. второй вариант
Re[5]: Как передать массив объектов в виде VARIANT
От: Vi2 Удмуртия http://www.adem.ru
Дата: 02.04.04 10:15
Оценка:
Здравствуйте, Plutonia Experiment, Вы писали:

Vi2>>sa = SafeArrayCreateEx( VT_DISPATCH, 1, & sabound, & IID_IAcadEntity );
Vi2>>sa = SafeArrayCreateEx( VT_DISPATCH | FADF_HAVEIID, 1, & sabound, & IID_IAcadEntity );
Vi2>>Я не знаю, какая строчка будет правильной — с или без FADF_HAVEIID.

PE>FADF_HAVEIID нужно, если передаешь IID. Т.е. второй вариант

А вот и не угадал!
Я написал так, потому что в функции SafeArrayCreateEx есть описание

vt
The base type or the VARTYPE of each element of the array. The FADF_RECORD flag can be set for a variant type VT_RECORD, The FADF_HAVEIID flag can be set for VT_DISPATCH or VT_UNKNOWN, and FADF_HAVEVARTYPE can be set for all other VARTYPEs.

Но нужно было бы проверить, а проверка показывает, что верен первый вариант, т.е. функция сама достаточно умная, чтобы это понять. Тем более, что FADF_HAVEIID — это битовое поле, а VT_DISPATCH — отнюдь.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[6]: Как передать массив объектов в виде VARIANT
От: Plutonia Experiment Беларусь http://blogs.rsdn.org/ikemefula
Дата: 02.04.04 10:31
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Но нужно было бы проверить, а проверка показывает, что верен первый вариант, т.е. функция сама достаточно умная, чтобы это понять. Тем более, что FADF_HAVEIID — это битовое поле, а VT_DISPATCH — отнюдь.


Я думал, что FADF_HAVEIID заставляет вставить IID в структуру SAFEARRAY.

pvExtra
Points to the type information of the user-defined type, if you are creating a safearray of user-defined types. If the vt parameter is VT_RECORD, then pvExtra will be a pointer to an IRecordInfo describing the record. If the vt parameter is VT_DISPATCH or VT_UNKNOWN, then pvExtra will contain a pointer to a GUID representing the type of interface being passed to the array.

Re: Как передать массив объектов в виде VARIANT
От: Plutonia Experiment Беларусь http://blogs.rsdn.org/ikemefula
Дата: 02.04.04 11:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Возникла острая необходимость написать небольшое приложение под AutoCAD с использованием OLE Automation. Документация по всему этому есть только для VBA, а я пишу на С++. В один из методов (штриховка контура) требуется передавать массив объектов, которые составляют контур в AutoCAD. Как это сделать на VBA описано в Help. Однако на основе этой информации я не понял, как это сделать на С++. Метод, сгенерированный в качестве обертки из TypeLibrary требует массив объектов


Итак, скриптовый клиент SAX Basic

Sub Main
    
Dim obj1 As New Class1
Dim arr(2) As Class2

Set arr(0) = New Class2
Set arr(1) = New Class2

obj1.TestArray(arr)
End Sub



interface IClass1 : IDispatch{
    [id(1), helpstring("method TestArray")] HRESULT TestArray([in] VARIANT array);
};



В метод приходит вариант с VT = 0x6009.

VT_DISPATCH = 9,
VT_ARRAY = 0x2000,
VT_BYREF = 0x4000,

Посколько пришел VT_BYREF, то надо заглядывать не в array.parray, а array.pparray.

array.pparray->fFeatures равняется 0x450

FADF_DISPATCH 0x0400
FADF_HAVEIID 0x0040
FADF_FIXEDSIZE 0x0010


Т.е. для С++ клиента надо сделать точно такой же Сейфаррей и передать его по ссылке в вариант.
Re[2]: Как передать массив объектов в виде VARIANT
От: Аноним  
Дата: 02.04.04 13:29
Оценка:
Здравствуйте, Plutonia Experiment, Вы писали:


PE>В метод приходит вариант с VT = 0x6009.


PE> VT_DISPATCH = 9,

PE> VT_ARRAY = 0x2000,
PE> VT_BYREF = 0x4000,

PE>Посколько пришел VT_BYREF, то надо заглядывать не в array.parray, а array.pparray.


PE>array.pparray->fFeatures равняется 0x450


PE> FADF_DISPATCH 0x0400

PE> FADF_HAVEIID 0x0040
PE> FADF_FIXEDSIZE 0x0010


PE>Т.е. для С++ клиента надо сделать точно такой же Сейфаррей и передать его по ссылке в вариант.



Спасибо за советы, и помощь. Все теперь работает как надо.
Ты меня очень сильно выручил. Возможно, в процессе написания возникнут еще проблемы,
тогда обращусь к тебе, если ты не против.

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

Для тех, у кого возникнут аналогичные проблемы, вот код, который я написал:

 //создаю массив
 SAFEARRAY* sa;
 sa = SafeArrayCreateVectorEx(VT_DISPATCH,0,1,(void*)&IID_IDispatch);

 //выставляю флаги
 sa->fFeatures = FADF_DISPATCH | FADF_HAVEIID | FADF_FIXEDSIZE;

 //получаю указатель на интерфейс IDispatch у смарт-указателя на IAcadPolyline
 IDispatch* pIAcadEntity;
 hr = Contur->QueryInterface(IID_IAcadEntity,(void **)&pIAcadEntity);
 if (FAILED(hr)) return;

 //добавляю в единственный элемент массива полученный указатель интерфейс
 long idx[1] = {0};
 hr = SafeArrayPutElement(sa,idx,pIAcadEntity);
 if (FAILED(hr)) return;

 //создаю Variant, в который надо обернуть SAFEARRAY для передачи в метод AppendOuterLoop
 VARIANT ConturArray;
 VariantInit(&ConturArray);
 ConturArray.vt = VT_ARRAY|VT_DISPATCH|VT_BYREF;
 ConturArray.pparray = &sa;

 //вызываю проблемный метод, который теперь отлично работает
 hr = iHatch->AppendOuterLoop(ConturArray);
 if (FAILED(hr)) return;

 //зачистка структур в памяти, дело до которой не доходит
 pIAcadEntity->Release();
 SafeArrayDestroy(sa);
Re[3]: Как передать массив объектов в виде VARIANT
От: Plutonia Experiment Беларусь http://blogs.rsdn.org/ikemefula
Дата: 02.04.04 13:34
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Ты меня очень сильно выручил. Возможно, в процессе написания возникнут еще проблемы,

А>тогда обращусь к тебе, если ты не против.

Валяй

А>А ты можешь подробнее описать, как проводил исследование чтобы узнать, какие биты передаются?

А>Может в будущем мне это поможет.

Создал проект на ATL. Добавил два простых объекта. В одном из объектов заимплементил метод с параметром вариантом. Поставил брякпоинт.

Запустил IDE Sax Basic. Подключил созданную DLL.
На бейсике написал тот код,что приводил раньше.

Запустил, вывалился в дебаг и постомтрел, что где и как передается.
Потом написал ответ сюда.
Re[3]: Как передать массив объектов в виде VARIANT
От: Vi2 Удмуртия http://www.adem.ru
Дата: 02.04.04 13:41
Оценка:
Здравствуйте, Аноним, Вы писали:

А> //создаю Variant, в который надо обернуть SAFEARRAY для передачи в метод AppendOuterLoop
А> VARIANT ConturArray;
А> VariantInit(&ConturArray);
А> ConturArray.vt = VT_ARRAY|VT_DISPATCH|VT_BYREF;
А> ConturArray.pparray = &sa;

А зачем использовать VT_BYREF? Чтобы поиметь проблемы? Ну и что что SAX Basic передает его как ByRef, он ведь за памятью следит автоматически, не то что С++.
ConturArray.vt = VT_ARRAY|VT_DISPATCH;
ConturArray.parray = sa;
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Как передать массив объектов в виде VARIANT
От: Аноним  
Дата: 03.04.04 04:42
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>

А>> //создаю Variant, в который надо обернуть SAFEARRAY для передачи в метод AppendOuterLoop
А>> VARIANT ConturArray;
А>> VariantInit(&ConturArray);
А>> ConturArray.vt = VT_ARRAY|VT_DISPATCH|VT_BYREF;
А>> ConturArray.pparray = &sa;

Vi2>А зачем использовать VT_BYREF? Чтобы поиметь проблемы? Ну и что что SAX Basic передает его как ByRef, он ведь за памятью следит автоматически, не то что С++.
Vi2>
Vi2>ConturArray.vt = VT_ARRAY|VT_DISPATCH;
Vi2>ConturArray.parray = sa;
Vi2>


VT_BYREF использовать надо, т.к при его отсутствии вышеназванный проблемный метод возвращает код ошибки
0x80070057 (E_INVALIDARG), т.е. не работает.
Re[3]: Где взять IID_IAcadEntity
От: andreyVC  
Дата: 09.01.06 08:50
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Plutonia Experiment, Вы писали:



PE>>В метод приходит вариант с VT = 0x6009.


PE>> VT_DISPATCH = 9,

PE>> VT_ARRAY = 0x2000,
PE>> VT_BYREF = 0x4000,

PE>>Посколько пришел VT_BYREF, то надо заглядывать не в array.parray, а array.pparray.


PE>>array.pparray->fFeatures равняется 0x450


PE>> FADF_DISPATCH 0x0400

PE>> FADF_HAVEIID 0x0040
PE>> FADF_FIXEDSIZE 0x0010


PE>>Т.е. для С++ клиента надо сделать точно такой же Сейфаррей и передать его по ссылке в вариант.



А>Спасибо за советы, и помощь. Все теперь работает как надо.

А>Ты меня очень сильно выручил. Возможно, в процессе написания возникнут еще проблемы,
А>тогда обращусь к тебе, если ты не против.

А>А ты можешь подробнее описать, как проводил исследование чтобы узнать, какие биты передаются?

А>Может в будущем мне это поможет.

А>Для тех, у кого возникнут аналогичные проблемы, вот код, который я написал:


А>
А> //создаю массив
А> SAFEARRAY* sa;
А> sa = SafeArrayCreateVectorEx(VT_DISPATCH,0,1,(void*)&IID_IDispatch);

А> //выставляю флаги
 sa->>fFeatures = FADF_DISPATCH | FADF_HAVEIID | FADF_FIXEDSIZE;

А> //получаю указатель на интерфейс IDispatch у смарт-указателя на IAcadPolyline
А> IDispatch* pIAcadEntity;
А> hr = Contur->QueryInterface(IID_IAcadEntity,(void **)&pIAcadEntity);
А> if (FAILED(hr)) return;

А> //добавляю в единственный элемент массива полученный указатель интерфейс
А> long idx[1] = {0};
А> hr = SafeArrayPutElement(sa,idx,pIAcadEntity);
А> if (FAILED(hr)) return;

А> //создаю Variant, в который надо обернуть SAFEARRAY для передачи в метод AppendOuterLoop
А> VARIANT ConturArray;
А> VariantInit(&ConturArray);
А> ConturArray.vt = VT_ARRAY|VT_DISPATCH|VT_BYREF;
А> ConturArray.pparray = &sa;

А> //вызываю проблемный метод, который теперь отлично работает
А> hr = iHatch->AppendOuterLoop(ConturArray);
А> if (FAILED(hr)) return;

А> //зачистка структур в памяти, дело до которой не доходит
А> pIAcadEntity->Release();
А> SafeArrayDestroy(sa);
А>


Я пытался сделать как написано в этом сообщении, но при компиляции получаю сообщение
error C2065: 'IID_IAcadEntityPtr' : undeclared identifier
Где взять IID_IAcadEntity

Я только начинаю изучать COM, OLE
поэтому наверное это неправильнй вопрос
помогите пожалуйста
заранее благодарен
Re[4]: Где взять IID_IAcadEntity
От: ekamaloff Великобритания  
Дата: 09.01.06 09:22
Оценка:
Здравствуйте, andreyVC, Вы писали:

VC>Я пытался сделать как написано в этом сообщении, но при компиляции получаю сообщение

VC>error C2065: 'IID_IAcadEntityPtr' : undeclared identifier
VC>Где взять IID_IAcadEntity

Для того, чтобы ты мог использовать AutoCAD в качестве Automation сервера, следует предварительно сымпортировать его библиотеку типов в твой проект. Один из наиболее простых путей — это использование директивы #import (можешь почитать статью "Директива #import"
Автор(ы): Игорь Ткачёв
Дата: 9.03.2001

В данной статье приводится объяснение работы директивы #import
компилятора Visual C++ и даны примеры её использования с
MS Word, MS Excel, ADO DB и ActiveX Control.
). В качестве filename можешь использовать например ProgID ("progid:AutoCAD.Application") или путь к главному исполняемому файлу AutoCAD-a (обычно библиотеки типов лежат в них).
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[5]: Где взять IID_IAcadEntity
От: andreyVC  
Дата: 09.01.06 09:33
Оценка:
Здравствуйте, ekamaloff, Вы писали:


E>Для того, чтобы ты мог использовать AutoCAD в качестве Automation сервера, следует предварительно сымпортировать его библиотеку типов в твой проект. Один из наиболее простых путей — это использование директивы #import (можешь почитать статью "Директива #import"
Автор(ы): Игорь Ткачёв
Дата: 9.03.2001

В данной статье приводится объяснение работы директивы #import
компилятора Visual C++ и даны примеры её использования с
MS Word, MS Excel, ADO DB и ActiveX Control.
). В качестве filename можешь использовать например ProgID ("progid:AutoCAD.Application") или путь к главному исполняемому файлу AutoCAD-a (обычно библиотеки типов лежат в них).


я сделал импорт acad.tlb — у меня AutoCAD2000

Вот мой код:
void CTestACADDlg::OnACAD()
{
using namespace AutoCAD;
::CoInitialize(NULL);
try
{
CLSID clsid ;
_com_util::CheckError(CLSIDFromProgID (L"AutoCAD.Application", &clsid));
IAcadApplicationPtr pApp;

if (FAILED(pApp.GetActiveObject(clsid)))
{
_com_util::CheckError(pApp.CreateInstance(clsid));
}
pApp->put_Visible(VARIANT_TRUE);
IAcadDocumentsPtr pDocs;
_com_util::CheckError(pApp->get_Documents(&pDocs));
IAcadDocumentPtr pDoc;
//_com_util::CheckError(pDoc = pDocs->Open(_bstr_t("c:\\downtown.dwg"),_variant_t(false)));

pDoc = pDocs->Add();
IAcadModelSpacePtr modsp;
modsp = pDoc->GetModelSpace();
IAcadCirclePtr circle;

double center[]={100,100,0};
COleSafeArray saCenter;
saCenter.CreateOneDim(VT_R8,3,center);

circle= modsp->AddCircle(saCenter,50);

IAcadEntityPtr entity;
entity =(IAcadEntityPtr)circle;
IAcadHatchPtr Hatch;
Hatch= modsp->AddHatch(0,"ANSI31",TRUE);

SAFEARRAY* sa;
sa = SafeArrayCreateVectorEx(VT_DISPATCH,0,1,(void*)&IID_IDispatch);
sa->fFeatures = FADF_DISPATCH | FADF_HAVEIID | FADF_FIXEDSIZE;


IDispatch* pIAcadEntity;
HRESULT hr;
hr = entity->QueryInterface(IID_IAcadEntityPtr,(void **)&pIAcadEntity);
if (FAILED(hr)) return;


long idx[1] = {0};
hr = SafeArrayPutElement(sa,idx,pIAcadEntity);
if (FAILED(hr)) return;


VARIANT ConturArray;
VariantInit(&ConturArray);
ConturArray.vt = VT_ARRAY|VT_DISPATCH|VT_BYREF;
ConturArray.pparray = &sa;


hr = Hatch->AppendOuterLoop(ConturArray);
if (FAILED(hr)) return;


pIAcadEntity->Release();
SafeArrayDestroy(sa);
}
catch(const _com_error e)
{
// if (e.ErrorMessage()!=NULL) acutPrintf("Error: %s",e.ErrorMessage());
}
::CoUninitialize();

}
Re[5]: Новый стиль GUID-ов
От: andreyVC  
Дата: 12.01.06 20:28
Оценка:
Здравствуйте, ekamaloff, Вы писали:

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


VC>>Я пытался сделать как написано в этом сообщении, но при компиляции получаю сообщение

VC>>error C2065: 'IID_IAcadEntityPtr' : undeclared identifier
VC>>Где взять IID_IAcadEntity

E>Для того, чтобы ты мог использовать AutoCAD в качестве Automation сервера, следует предварительно сымпортировать его библиотеку типов в твой проект. Один из наиболее простых путей — это использование директивы #import (можешь почитать статью "Директива #import"
Автор(ы): Игорь Ткачёв
Дата: 9.03.2001

В данной статье приводится объяснение работы директивы #import
компилятора Visual C++ и даны примеры её использования с
MS Word, MS Excel, ADO DB и ActiveX Control.
). В качестве filename можешь использовать например ProgID ("progid:AutoCAD.Application") или путь к главному исполняемому файлу AutoCAD-a (обычно библиотеки типов лежат в них).


Прочитал статью про директиву импорт.
Но в ней нет необходимой информации.
В самом начале есть ссылка на MSDN, где и нашелся ответ.
Это аттрибут named_guids:

The named_guids attribute
The named_guids attribute tells the compiler to define and initialize GUID variables in old style, of the form LIBID_MyLib, CLSID_MyCoClass, IID_MyInterface, and DIID_MyDispInterface.


#import "C:\Program Files\ACAD2000\acad.tlb" named_guids

И всё нормально компилируется.

Как написано в MSDN – это старый стиль.
А какой новый стиль (то есть используемый в настоящее время)?
Если можно, приведите, пожайлуста, какой-нибудь пример получения IID и работы с GUID-ами в новом стиле.

P.S. У кого-нибудь есть ссылка на электронный вариант Inside OLE или что-нибудь про COM. Наверное я не умею правильно задавать вопросы Гуглу: выдаёт сплошную рекламу дисков с электронными книгами (прости меня, Гугл)
Re[6]: Новый стиль GUID-ов
От: ekamaloff Великобритания  
Дата: 13.01.06 03:47
Оценка:
Здравствуйте, andreyVC, Вы писали:

VC>Как написано в MSDN – это старый стиль.

VC>А какой новый стиль (то есть используемый в настоящее время)?
VC>Если можно, приведите, пожайлуста, какой-нибудь пример получения IID и работы с GUID-ами в новом стиле.

Видимо под новым стилем имеется ввиду (на примере MSHTML):

вместо MSHTML::CLSID_HTMLDocument

__uuidof(MSHTML::HTMLDocument)


вместо MSHTML::IID_IHTMLDocument2

__uuidof(MSHTML::IHTMLDocument2)


вместо MSHTML::DIID_DispHTMLDocument

__uuidof(MSHTML::DispHTMLDocument)


вместо MSHTML::LIBID_MSHTML

__uuidof(MSHTML::__MSHTML)
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.