Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Вопрос по автоматизации  (Прочитано 14872 раз)
0 Пользователей и 1 Гость смотрят эту тему.
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« : 01-06-2006 15:08 » 

Здравствуйте.

Есть небольшая проблема при автоматизации приложений.

Есть программа Adobe Illustrator.
Есть возможность использовать ее как сервер автоматизации следующим образом:

    Variant AI = CreateOleObject("Illustrator.Application.1");
    _ApplicationDisp * AIApp = new _ApplicationDisp(AI.VDispatch);
    _DocumentsDisp * Documents = new _DocumentsDisp(AIApp->Documents);
    _DocumentDisp * Document = new _DocumentDisp(Documents->Add(TNoParam, TNoParam, TNoParam));
   ...
   delete Document;
   delete Documents;
   delete AIApp;
   AI = Unassigned;

Вот только не получается.
Проблема возникает при использовании класса TNoParam (используется в случае, если на место опционального параметра функции приложения подставлять ничего не надо).
В помощи описывается именно такой способ, какой показан выше.
Но при попытке скомпилировать прогу выскакивает ошибка:

[C++ Error] utilcls.h(2334): E2031 Cannot cast from 'const TBaseVariantT<tagVARIANT>' to 'TVariant &'

И никакими средствами конвертации эта ошибка не лечится.

Кто знает в чем дело - помогите!!!

Заранее спасибо!
« Последнее редактирование: 14-12-2007 15:28 от Алексей1153++ » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 01-06-2006 18:00 » new

Скорее всего проблема в том, что TNoParam — это класс, а не объект класса. Передача в качестве параметра имени класса бессмысленна, а чтобы создать объект, нужно вызывать конструктор.

Если предположение верно, то правильно будет:
Код: (C++)
_DocumentDisp * Document = new _DocumentDisp(Documents->Add(TNoParam(), TNoParam(), TNoParam()));
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 01-06-2006 20:03 » 

Делал и так тоже...
Ничего не меняется. Даже содержание ошибки не меняется, блин! Улыбаюсь

Но ведь самое интересное, что в помощи билдеровской написано именно БЕЗ СКОБОК!!!

Но вот в продолжение.
По строке 2334 файла 'utilcls.h' находится следующий текст (строки, на всякий случай, я пронумеровал):
//-------------------------------------------------------

2329  TVariantT& operator =(const TBaseVariantT<T>& rhs)
2330  {
2331    if (&rhs != this)
2332    {
2333      ::VariantClear(this);
2334      ::VariantCopy(this, &(const_cast<TVariantT&>(rhs)));    //<--вот эта строка
2335    }
2336    return *this;
2337  }

//-------------------------------------------------------

Сгенерирован этот текст был автоматом при импорте библиотеки типов.

Пытался делать даже нечто невообразимое:
TNoParam() << v
где v - переменная типа Variant.

Ошибка, естественно, звучит так:
[C++ Error] AI.cpp(31): E2094 'operator<<' not implemented in type 'TNoParam' for arguments of type 'TVariant'

Вот такая автоматизация...
Или я, скорее всего, не знаю какую-то мелочь... Какое-то зарезервированное слово... (Звучит как "волшебное слово")
Если кто знает - научите, пожалуйста!
« Последнее редактирование: 14-12-2007 15:28 от Алексей1153++ » Записан
Alf
Гость
« Ответ #3 : 01-06-2006 20:48 » 

Попробуй еще так:

Код:
TNoParam noParam;
_DocumentDisp * Document = _DocumentDisp(Documents->Add(noParam, noParam, noParam));

или

Код:
TNoParam *noParam = new TNoParam();
_DocumentDisp * Document = _DocumentDisp(Documents->Add(noParam, noParam, noParam));
...
delete noParam;
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 01-06-2006 21:00 » 

В таком случае, когда автоматическое приведение не срабатывает, класс TBaseVariantT<tagVARIANT> не является потомком класса TVariantT. Посмотри по коду, каковы их отношения. Возможно, из-за шаблонов где-нибудь необходимо квалификатор typename поставить.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 02-06-2006 07:20 » 

2 Alf
Пытался и так делать. Та же самая ошибка выскакивает!!!

Опишу ситуацию полностью. (Прошу прощения, что не сделал этого раньше.)

Описание функции выглядит следующим образом:

Documents->Add(TVariantInParam DocumentColorSpace = TNoParam(), TVariantInParam Width = TNoParam(), TVariantInParam Height = TNoParam())

У класса TNoParam есть операторы преобразования типа, которые так и называются
'TVariantInParam *' и 'TVariantInParam *' (см. ниже)!
Т. е. преобразование происходит, имхо, автоматом тогда и так, когда и как это надо.

Далее. Про отношения классов.

Вот объявление класса TBaseVariantT (файл utilcls.h строки с 885 по 1293):
template <class T> class TBaseVariantT : public T
{ .... }

Вот объявление класса TVariantInParamT (файл utilcls.h строки с 1295 по 2000):
template <class T> class TVariantInParamT : public TBaseVariantT<T>
{ .... }

Вот объявление класса TVariantT (файл utilcls.h строки с 2002 по 2691):
template <class T> class TVariantT : public TBaseVariantT<T>
{ .... }
typedef TVariantInParamT<VARIANT> TVariantInParam;
typedef TVariantT<VARIANT>        TVariant;


Вот объявление класса TNoParam (файл utilcls.h строки с 3175 по 3195):
class TNoParam
{
public:
  TNoParam()
  {
    m_Variant.vt = VT_ERROR;
    V_ERROR(&m_Variant) = DISP_E_PARAMNOTFOUND;
  }

  operator VARIANT*  ()         { return &m_Variant;}
  operator VARIANT&  ()         { return m_Variant; }
  operator TVariant* ()         { return &m_Variant;}
  operator TVariant& ()         { return m_Variant; }
  operator TVariantInParam* ()  { return &(TVariantInParam)m_Variant;}
  // note: c++ semantics do not allow returning a reference here,
  // so we go ahead and do the (pointless) copy.
  operator TVariantInParam ()   { return m_Variant;}

private:
  TVariant m_Variant;
};

Файл utilcls.h родной билдеровский. Есть у каждого.

Т.е., как я понимаю, TNoParam->m_Variant попадает с преобразованием к TBaseVariantT в ту глючную функцию, а потом (в строке 2334) преобразовывается обратно к родному типу TVariantT???

2 dimka
Просто я в шаблонах не силен пока: только недавно начал изучать.
« Последнее редактирование: 14-12-2007 15:30 от Алексей1153++ » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 02-06-2006 09:46 » 

Цитата: direcktorSan
Documents->Add(TVariantInParam DocumentColorSpace = TNoParam(), TVariantInParam Width = TNoParam(), TVariantInParam Height = TNoParam())
Здесь определены значения по умолчанию. Когда все параметры отсутствуют, вызов Add может производиться без параметров:
Код: (C++)
_DocumentDisp * Document = new _DocumentDisp(Documents->Add());

Цитата: directorSan
template <class T> class TBaseVariantT : public T { ... };
template <class T> class TVariantT : public TBaseVariantT<T> { ... };
typedef TVariantT<VARIANT> TVariant;
Ну да, во-первых, если
Цитата: directorSan
cast from 'const TBaseVariantT<tagVARIANT>' to 'TVariant &'
, то это, получается, downcast (от предка к потомку), который автоматически не выполняется в run time. Во-вторых, и это главное, тип TVariantT в строчке 2334 является параметризируемым, а параметр там пропущен. Поэтому, во-первых, попробуй такое изменение:
Код: (C++)
::VariantCopy(this, &(const_cast<typename TVariantT<T> &>(rhs)));

А если не поможет, тогда попытайся провести явное преобразование: замени тело условия (строчки 2333-2334) на
Код: (C++)
try
{
  ::VariantClear(this);
  // Если преобразование не пройдёт, возникнет исключение bad_cast.
  typename TVariantT<T> &v = dynamic_cast<typename TVariantT<T> &>(const_cast<typename TBaseVariantT<T> &>(rhs));
  ::VariantCopy(this, &v);
}
catch(bad_cast)
{
  ... // Здесь обработка исключения.
}

Для доступа к классу bad_cast подключи в начале заголовочный файл <typeinfo.h>.
« Последнее редактирование: 14-12-2007 15:32 от Алексей1153++ » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 02-06-2006 11:13 » 

И так тоже пытался:
_DocumentDisp * Document = new _DocumentDisp(Documents->Add());

Та же самая фигня получается... Жаль
А про остальное сейчас попробую.
Записан
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 02-06-2006 11:39 » 

Сделал сперва так:
::VariantCopy(this, &(const_cast<typename TVariantT<T> &>(rhs)));

Ошибка та же на этой строке.

Потом сделал так:

  // --- НЕ родной вариант ---
  TVariantT& operator =(const TBaseVariantT<T>& rhs)
  {
    if (&rhs != this)
    {
      try
        {
          ::VariantClear(this);
          // Если преобразование не пройдёт, возникнет исключение bad_cast.
          typename TVariantT<T> &v =
             dynamic_cast<typename TVariantT<T> &>
               (const_cast<typename TBaseVariantT<T> &>(rhs)); //<-- ЗДЕСЬ ошибка лезет
          ::VariantCopy(this, &v);
        }
      catch(bad_cast)
        {// Здесь обработка исключения.
        };
    }
    return *this;
  }
  // --- НЕ родной вариант ---
Текст ошибки:
[C++ Error] utilcls.h(2355): E2307 Type 'TBaseVariantT<tagVARIANT>' is not a defined class with virtual functions

Хочу обратить внимание, что ошибка лезет в момент компиляции. До запуска дело не доходит.

Товарищи!
Спасибо вам за ответы! Извините, что напрягаю!
НО УЖ ОЧЕНЬ ДО СУТИ ДОКОПАТЬСЯ ХОЧЕТСЯ!..

Ведь до Иллюстратора более или менее нормально получилось автоматизировать Adobe InDesign (с этим проблем пока было меньше всего) и CorelDraw (пришлось немного повозиться)! А вот с Иллюстратором трабл...
« Последнее редактирование: 14-12-2007 15:33 от Алексей1153++ » Записан
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 02-06-2006 11:40 » 

Мне тут еще посоветовали вот эти темы посмотреть:

посмотри здесь: http://forum.codenet.ru/showthread.php?threadid=7127
или здесь: http://beta-lists.topica.com/lists/cbuilder/read/message.html?sort=t&mid=1701088788

Если так заработает - сразу же скажу!
Записан
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 02-06-2006 12:03 » 

Заработало!

В принципе в обеих темах советуется одно и то же.
Но я, собственно, тоже не сторонник изменения родных билдеровских заголовочных файлов.

Посоветовал PooH. Спасибо!

(Просто я, случайно, разместил такое же сообщение в архиве вопросов по программированию... Случайно! Чессслово!.. Краснею )

Спасибо всем!
Но если найдется, все-таки, другое решение - заранее благодарен за совет!
Удачи!!!
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 02-06-2006 13:06 » 

Цитата: directorSan
'TBaseVariantT<tagVARIANT>' is not a defined class with virtual functions
Это, надо понимать, означает, что TBaseVariantT или tagVARIANT + абстрактный класс, содержащий "= 0" методы.

Цитата: directorSan
Про C++B не знал, но догадывался, а вот в Delphi точно натыкался на проблемы при импорте библиотек. Глюки среды.
« Последнее редактирование: 14-12-2007 15:31 от Алексей1153++ » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines