FR в Dll + DataSet

отредактировано August 2006 Раздел: FastReport 3.0
Я пишу в среде Delphi7, отчет пишу на FR 3.18, использую для доступа к данным FIB6.2. Модуль подготовки, формирования и печати отчета вынес в Dll где описал функцию:

function ShowReport
(
HandleMain : cardinal; //- Хэндл главного окна
FullPathReport: string; //- Полный путь к шаблону отчета
masterDataSet: TDataSet //- Датасет который выдает линейную таблицу
): PChar; stdcall;
... //- все переменные описываю
try
SaveHandle := Application.Handle; //- Сохраняю родной хэндл
Application.Handle := HandleMain; //- форме присваиваю хэндл вызывающего приложения
FormReport := TFormReport.Create(Application); //- Создаю форму
Application.ProcessMessages; //- На которой я разместил компоненты:
frxFIBMaster.DataSet:=masterDataSet; //- TfrxReport, TfrxDBDataset, TfrxDesigner и на всякий случай TfsDBCtrlsRTTI,TfsDBRTTI
frxReport.LoadFromFile(FullPathReport) //- Загружаю шаблон отчета
frxReport.ShowReport(true); //- Показываю уже сформированный отчет
//- Все работает. Супер!! Но как только я его закрываю обламывается всё приложение как по цепной реакции, хотя везде стоят try
except on E: Exception do
Result := PChar(E.Message);
end;
Application.Handle := SaveHandle; //- Возвращаю свой хэндл
FormReport.Free; //- Высвобождаю форму

Вопрос состоит в том как сделать что бы не происходило обвала приложения и модуля вызывающего Dll которая содержит отчет FR?
Выслушаю всех и всё.

Комментарии

  • отредактировано 21:05
    Неужели ни у кого нет что сказать. Может все в отпусках или жара замучила.
    Тогда я скажу. Поигравшись с параметрами, вспомнил что в dll вместо string лучше передавать pchar, а уже внутри его преобразовать.
    Пробовал и так и сяк
    // FullPathReport:= String(fFullPathReport);
    // StrCopy(FullPathReport, fFullPathReport);
    но проблему не решило.
    Ещё кто выскажется? ;)
  • отредактировано 21:05
    Я так понял, что идет неявный вызов библиотеки с ФР. Я всегда использую явный вызов: когда надо вызвал, чего надо поделал и выгрузил все, а основная программа работает дальше, ошибок гораздо меньше при этом, если соблюдать определенные правила. Вообще то, насколько я помню, в случае неявного вызова надо Аппликатион хэндл в конце работы присваивать 0. Если падает с Аксесс вайолетионом, нужно очень внимательно смотреть за высвобождением ресурсов, которые насоздовала Длл. А по поводу строк я соблюдаю следующее правило: внутри приложений всегда стринг, а при передаче во внешние программы использую Пчар.
  • отредактировано 21:05
    Да, забыл, высбождение ресурсов ставить в блок трай -финалли.
  • отредактировано 21:05
    Спасибо за ответ. Использую я динамический вызов DLL, с этим проблем нет. Попробовал различные варианты. Когда я вызываю модуль dll из ехе, трєй отрабатывает четко, даже в тех случаях когда присутсвут ошибки в самомо отчете. Просто отражается текст ошибки. Далее высвобождается память в блоке finally, остальное приложение продолжает функционировать как и полагается.
    Но если я из программы вызываю модуль dll, а потом из модуля dll вызываю отчет FR в другом dll, следует обвал по закрытию. Причем запуская под дебагером пару раз ексепшн был не из-за виолешн-а, а что то типа "слишком много трэй эксепшенов".
    Вот начал переоборудовать, упрощать, убирал параметры, но ошибки остались.
    Помогите пожалуста. ;)
    Я думаю интересно было бы использовать FR в dll.
    Поробовать как вариант поручить ехе вызывать две dll и печатать через основную программу. Парюсь дальше.
    Есть варианты?
  • отредактировано 21:05
    При поиске решения самым эффективным оказался "дедовский метод". А ошибка возникала в из-за обработки алиасов DataSet-a внутри dll, вот эта реализация:

    function GetFieldAliases(сDataSet: TDataSet) : string;
    var k : integer;
    begin
    Result := сDataSet.Fields[0].Name+'='+сDataSet.Fields[0].FieldName;
    for k:=1 to сDataSet.FieldCount-1 do
    Result := Result+ #13 + сDataSet.Fields[k].FieldName+'='+сDataSet.Fields[k].DisplayName;
    end;
    ...
    ; if not (masterDataSet=nil)
    ; then begin
    ; frxFIBMaster.DataSet:=masterDataSet;
    ; frxFIBMaster.FieldAliases.Text := GetFieldAliases(masterDataSet);
    ; end;
    ...

    Как поправлю всё выложу рабочий вариант что бы другие могли тоже им воспользоваться.
    PS. Учится лучше на чужих ошибках.
  • отредактировано 21:05
    написал:
    Но если я из программы вызываю модуль dll, а потом из модуля dll вызываю отчет FR в другом dll, 

    Какая интересная реализация... ;)
    написал:
    Я думаю интересно было бы использовать FR в dll.

    Это не только интересно, но и полезно, сам так делаю ;)
    написал:
    Поробовать как вариант поручить ехе вызывать две dll и печатать через основную программу.

    А зачем вообще так все усложнять, понятно, что будут ошибки с распределением памяти, высвобождением ресурсов etc, не проще ли начать с того, что есть екзе, а есть длл с ФР, и все сначала оттестировать так, а уже потом усложнять. Кста, когда создаете объекты в ДЛЛках, кого указываете в качестве родителя, случаем не Аппликатион?
  • отредактировано August 2006
    vadson6666 написал:
    vadson6666 написал:
    Но если я из программы вызываю модуль dll, а потом из модуля dll вызываю отчет FR в другом dll, 
    Какая интересная реализация... ;)
    Ниужели невозможно предположить что кроме ехешки, другие модули dll тоже хотели бы вызывать FR в dll. Что тут странного?
    Другое дело что есть ряд ограничений которые наклыдываются на объекты экспортируемые из Dll.
    vadson6666 написал:
    Кста, когда создаете объекты в ДЛЛках, кого указываете в качестве родителя, случаем не Аппликатион?
    Указываю хэндл аппликэйшина, не указывать же мне хэндл винды. А если не присваивать в модуле никакого хэндла, то на панели задач появляется его иконка , а при закрытии модуля аппликэйшн сворачивается.

    Это всё лирика, а корень зла лежал ещё глубже. Дело в том что в самом репорте выводятся строчки содержащие StringField-ы. Упс, а я должен всё передать через Pchar (одно из ограничений). Вот после этого все и ложилось.
  • отредактировано 21:05
    Да, действительно реализация заслуживает уважения ;) Может проще не "размазывать" FastReport по нескольким dll, а реализовать все в одной, а потом уж пусть другие dll ее вызывают? Или я что-то не так понимаю?
  • отредактировано 21:05
    YuraZ написал:
    Да, действительно реализация заслуживает уважения ;) Может проще не "размазывать" FastReport по нескольким dll, а реализовать все в одной, а потом уж пусть другие dll ее вызывают? Или я что-то не так понимаю?
    Отлично, я нашел единомышленника.
    Действительно, было бы замечательно из любого модуля, пусть то ехе или dll, вызывать FR из dll. Всё было бы ничего но та функциональность которая испольфуется в FR пересекается с ограничениями передаваемой информации из/в dll.
    Повторюсь что когда идет вызов FR(dll) из exe, отчет формируется нормально и имеющиеся ексепшены отрабатывают нормально.
    Если вызовается FR(dll) из другой dll, то вступают в действия ограниения и получается я не могу спокойно передать в отчет датасеты содержащие стринговые fields.
  • отредактировано 21:05
    ShareMem
    плюс общие пакеты run-time

  • отредактировано 21:05
    Delphi7, FR 3.23
    Приложение с плагинной архитектурой на основе Jedi (компонент JvPluginManager)
    Плагины реализованы как dll
    Разные плагины через интерфейс пользуют движок отчетов FR, реализованный в одной dll.
    Все нормально, проблем со строками нет.

Оставить комментарий

Многофункциональный текстовый редактор. Чтобы отредактировать стиль параграфа, нажмите TAB, чтобы перейти к меню абзаца. Там вы можете выбрать стиль. По умолчанию не выбран ни один стиль. Когда вы выберете текст, появится встроенное меню форматирования. Нажмите TAB, чтобы войти в него. Некоторые элементы, такие как многофункциональные вставки ссылок, картинок, индикаторов загрузки и сообщений об ошибок могут быть вставлены в редактор. Вы можете перемещаться по ним, используя стрелки внутри редактора и удалять с помощью клавиш delete или backspace.