Лоцман и Visual C++

Автор Хомутов, 08.09.08, 14:30:55

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

Хомутов

Здравтвуйте.
Я программирую в Visual C++.
То что Лоцман "заточен" под Delphi я уже понял. Тем не менее в Лоцмане предусмотрена возможность подключения плагинов, написанных на других языках.
Для этого используются такие же экспортируемые плагином функции что и в Delphi-плигинах, но с суффиксом Ex.
Проблема состоит в том что функции API Лоцмана, возвращающие наборы данных, если я правильно понимаю, предназначены для использования компонента TClientDataSet. Но в Visual Studio нет такого компонента.
Вопрос собственно такой: Как же мне все-таки работать с этим набором данных? А точнее как использовать такие функции в Visual Studio?

Muk

Может глупость скажу, но наверное переключить MainSystem в режим "отдачи" пакетов TClientDataSet в виде XML и потом их парсить через MSXML. Структура пакетов там простая совсем. Видимо так и работает PHP-код лоцмановского Web-клиента.

Хомутов

Спасибо большое.
Это действительно выход.

AI

В Лоцман 8.5 СП2 и Лоцман 9 можно получать данные в виде СОМ-объектов - так еще удобнее.

Хомутов

Спасибо. Это новость для меня.
Может скажете где можно какую-нибудь документацию по этому вопросу?

Хомутов

Попробовал я использовать возможности получения данных в виде COM-объектов.
Проблемы такие:
1. Не могу получить имя сервера приложений где Loodsman Server Application стоит. (очень нужно)
2. Не понятно зачем в
bool PgiCheckMenuItemCom(char const * stFunction, [glow=red,2,300]IPluginCall * pIPC[/glow])
нужен параметр pIPC. Ведь все равно когда с ним работаешь, либо ошибка выскакивает, либо PgiCheckMenuItemCom просто не работает
3. При написании своего клиента все равно нужно работать с API Loodsman Server Application. Тогда опять встает вопрос об обработке набора данных. Выход опять - xml формат.

Хомутов

Продолжаю свой монолог.

Как оказалось - самый нормальный способ написания плагинов - это использование "...Ex" функций инициализации плагина и работа с работа с сервером приложений напрямую.
Обработку же возвращаемых наботов данных производить с применением интерфейса IDataSet (который предоставляет "универсальный клиент" Лоцмана) , без всякого переклячения в режим xml.

Минус только один - необходимо создавать новое подключение к серверу приложений отдельно для плагина. Черевато это тем, что сервер лицензий может ругнуться раньше времени. На плагин наверное тоже лицензия требуется (точнее на подключение плагина к серверу приложений).

Muk

Цитата: Хомутов от 11.09.08, 11:31:03Как оказалось - самый нормальный способ написания плагинов - это использование "...Ex" функций инициализации плагина и работа с работа с сервером приложений напрямую.
Обработку же возвращаемых наботов данных производить с применением интерфейса IDataSet (который предоставляет "универсальный клиент" Лоцмана) , без всякого переклячения в режим xml.
А где это все описано?

Хомутов

Честно говоря - я не знаю.
Просто смотрел примеры. Пробовал сам что-то делать. Вот и все. :(

Конечно было бы неплохо иметь нормальную документацию под рукой.

AI

Попробую превратить монолог в диалог  :)

Почему не работает PgiCheckMenuItemCom? И что за ошибка выскакивает?

Пример, который я выкладывал, вполне рабочий

AI

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

По поводу одновременного обработки возвращаемых значений с помощью IDataSet, я правильно понимаю, что Вы присваиваете возвращаемое значение типа TClientDataSet в свойство Data объекта IDataSet?

Хомутов

Пример-то рабочий.
Проблема в том, что когда пытаешься внутри PgiCheckMenuItemCom использовать параметр IPluginCall * IPC, плагин начинает вести себя не предсказуеммо (могут выскакивать ошибки кажется доступа к памяти, а могут и не выскакивать). Хотя нет. Предсказуемо одно - функция просто не работает. Смысл функции - определение активности (не активности) пункта меню, но когда работаешь с параметром IPC - соответствующие плагину пункты меню становятся активными в любом случае.

Когда отладчиком проходишь - все всроде-бы нормально. И функция полностью отрабатывает. Но после завершения работы функции может выскочить ошибка. И не зависимо от того как отработала функция (от возвращаемого значения), результат один - пункт меню плагина активен

AI

Давайте код посмотрим

Хомутов

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

По поводу одновременного обработки возвращаемых значений с помощью IDataSet, я правильно понимаю, что Вы присваиваете возвращаемое значение типа TClientDataSet в свойство Data объекта IDataSet?

На счет IDataSet - Вы абсолютно правы.

Подключаться напрямую - не плохо. Забирается лицензия - не хорошо.
Почему? Да потому что подругому не работает. Кажется где-то я видел вот такое:

ЦитироватьКлиент различает delphi и НЕ-delphi -плагины, по наличию в них экспортной процедуры InitUserDll. В delphi-плагине она должна быть, а в НЕ-delphi плагине вместо нее должна быть InitUserDllEx, аналогично вместо PgiCheckMenuItem должна быть PgiCheckMenuItemEx.

Информация о выбранном объекте передается в виде структуры (struct - в С++, record - в паскале). Для обращения в СП создается собственное DCOM- соединение, при этом используется информация из полей структур: stAppServerName, stDataBaseName, stCheckoutName.

Было бы неплохо если бы  InitUserDllCom и PgiCheckMenuItemCom работали нормально.


AI

Да нормально они работают  :) Выложите код или лучше архив всего проекта

Хомутов

Например вот так.
Просто внес изменения в Ваш пример. Было так:
Цитировать__declspec(dllexport) bool __stdcall PgiCheckMenuItemCom(char const * stFunction, IPluginCall * IPC)
{
   if(strcmp(stFunction, "ProjectList") == 0)
      return true;
   if(strcmp(stFunction, "LinkedFast") == 0)
      return true;
   return false;
}
Стало вот так:
Цитировать__declspec(dllexport) bool __stdcall PgiCheckMenuItemCom(char const * stFunction, IPluginCall * IPC)
{
   _bstr_t sType;
   HRESULT hr = IPC->get_stType(sType.GetAddress());
   if(sType == _bstr_t("Технический проект"))
      return false;
   if(strcmp(stFunction, "ProjectList") == 0)
      return true;
   if(strcmp(stFunction, "LinkedFast") == 0)
      return true;
   return false;
}
Внесенные изменения никаким образом не повлияли на работу функции. А должны были  :o:

AI

У меня это работает

Вы точно хотели отключать пункт меню, если выбран объект типа "Технический проект"?

Хомутов


AI

У меня вот такой код делает неактивным пункт меню, если выбрана не папка

_bstr_t sType;
HRESULT hr = IPC->get_stType(sType.GetAddress());
if(sType != _bstr_t("Папка"))
  return false;

Хомутов

Зарботало. :-)))

Причина в том, что я в отладочном режиме компилировал.
Если переключить в Release, то все работает.

Уже лучше. Спасибо. (Только теперь отладчиком не воспользуешся  :-\)