Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

передача процедуры в процедуре [D7, Postgres]


alexey_mas ©   (2007-05-10 11:23:00) 

Добрый день!

помогите определить правильно процедуру в дельфях.
Использую компоненты ZEOS для подключения к базе Postgres.
Пытаюсь получить все сообщения с сервера при помощи Notice Processing

procedure Tdog_transfer_form.NoticeTransfer(arg:Pointer;messages:PChar);cdecl;
        begin
        Memo1.lines.Add(messages);
        end;

procedure Tdog_transfer_form.Button1Click(Sender: TObject);
       
var
    Driver: IZPostgreSQLPlainDriver;
    Conn: PZPostgreSQLConnect;
    Arg: Pointer;
begin
Driver := (PasswordDlg.ZConnection1.DbcConnection as IZPostgreSQLConnection).GetPlainDriver;
Conn := (PasswordDlg.ZConnection1.DbcConnection as IZPostgreSQLConnection).GetConnectionHandle;

Driver.SetNoticeProcessor(conn,NoticeTransfer,arg);   - вот здесь я указываю вторым параметром процедуру NoticeTransfer которая будет обрабатывать сообщения сервера
также здесь вылетает ошибка [Error] dog_transfer.pas(75): Incompatible types: 'regular procedure and method pointer'
end;


в исходных кодах компонента процедура определена так:


procedure TZPostgreSQL7PlainDriver.SetNoticeProcessor(
 Handle: PZPostgreSQLConnect; Proc:TZPostgreSQLNoticeProcessor;
 Arg: Pointer);
begin
 ZPlainPostgreSql7.PQsetNoticeProcessor(Handle, Proc, Arg);
end;

в свою очередь

TZPostgreSQLNoticeProcessor = procedure(arg: Pointer; message: PChar); cdecl;


Где я не так процедуру объявляю или вызываю?

Заранее спасибо.


alexey_mas   (2007-05-10 18:08:00) [1]

messages:PChar - это сообщения от сервера Postgres (Notice and warning messages generated by the server)

идея состоит в том что во время выполнения удаленных процедур все сообщения сразу же транслируются в мемо.

Пока получилось используя глобальную переменную объявленную в модуле _global_str выводить сообщения после окончания операций с сервером.

Привожу весь код модуля

unit dog_transfer;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ExtCtrls, DB, ZAbstractRODataset, ZAbstractDataset,
 ZDataset, ZConnection,ZPlainPostgreSql8,ZPlainPostgreSqlDriver,ZDbcPostgreSql;

type
 Tdog_transfer_form = class(TForm)
   Memo1: TMemo;
   Panel1: TPanel;
   Edit1: TEdit;
   Edit2: TEdit;
   Label1: TLabel;
   Label2: TLabel;
   Button1: TButton;
   Button2: TButton;
   ZQuery1: TZQuery;
   ZQuery2: TZQuery;
   procedure Button1Click(Sender: TObject);

 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 dog_transfer_form: Tdog_transfer_form;
 _global_str:string;

implementation
  uses password;
{$R *.dfm}

procedure NoticeTransfer(arg:Pointer;messages:PChar);cdecl;
       var
       _tmp_str:string;
       text_file:textfile;

       begin
       _tmp_str:=Trim(String(messages));

        if ((_tmp_str<>'') and (_tmp_str<>'NOTICE:')) then begin
        if pos('BASE64~|~',_tmp_str)=0  then _global_str:=_global_str+#13+#10+_tmp_str;
        UniqueString(_tmp_str);
        dog_transfer_form.Memo1.lines.Add('test'+_tmp_str);
        end;

        end;

procedure Tdog_transfer_form.Button1Click(Sender: TObject);

var
Driver: IZPostgreSQLPlainDriver;
Conn: PZPostgreSQLConnect;
 Arg: Pointer;
 idtransact:integer;
 id_shema:string;
 CallBackNoticeTransfer:TZPostgreSQLNoticeProcessor;

begin

  id_shema:='9';

  Driver := (PasswordDlg.ZConnection1.DbcConnection as IZPostgreSQLConnection).GetPlainDriver;
  Conn := (PasswordDlg.ZConnection1.DbcConnection as IZPostgreSQLConnection).GetConnectionHandle;

  PasswordDlg.ZConnection1.StartTransaction;
   arg:=Tdog_transfer_form.MethodAddress(Memo1.Text);

 try
  idtransact:=Driver.GetBackendPID(conn);

  Memo1.lines.Add('Получен PID = '+intToStr(idtransact));

//   CallBackNoticeTransfer:=@NoticeTransfer;
//   Driver.SetNoticeProcessor(conn,CallBackNoticeTransfer,arg);
  Driver.SetNoticeProcessor(conn,NoticeTransfer,arg);

  ZQuery1.Close;
  ZQuery1.SQL.Clear;
  ZQuery1.SQL.Text:='select * from dog_inittransfer(:idtrans)';
  ZQuery1.ParamByName('idtrans').AsInteger:=idtransact;
  ZQuery1.ExecSQL;

  ZQuery2.Close;
  ZQuery2.SQL.Clear;
  ZQuery2.SQL.Text:='insert into init_transfer(idobj,paramcode,data) values (cast(:idobj as integer),cast(:paramcode as varchar),cast(:data as varchar))';
  ZQuery2.ParamByName('idobj').AsInteger:=idtransact;
  ZQuery2.ParamByName('paramcode').AsString:='DATA_ID';
  ZQuery2.ParamByName('data').AsString:=id_shema;
  ZQuery2.ExecSQL;

  ZQuery2.Close;
  ZQuery2.SQL.Clear;
  ZQuery2.SQL.Text:='select * from dog_transfer(cast(:piddog as integer),cast(:plpwd as varchar),cast(:puser as text),cast(:ppwd as text),cast(:ptypeoper as varchar),cast(:pidobj as text),cast(:pidtr as integer) )';
  ZQuery2.ParamByName('piddog').AsInteger:=idtransact;
  ZQuery2.ParamByName('plpwd').AsString:=Driver.GetPassword(conn);
  ZQuery2.ParamByName('puser').AsString:=Trim(Edit1.Text);
  ZQuery2.ParamByName('ppwd').AsString:=Trim(Edit2.Text);
  ZQuery2.ParamByName('ptypeoper').AsString:='DATA';
  ZQuery2.ParamByName('pidobj').AsString:='';
  ZQuery2.ParamByName('pidtr').AsInteger:=idtransact;
  ZQuery2.ExecSQL;

  Memo1.lines.Add('Получены данные от dog_transfer');

  ZQuery2.Close;
  ZQuery2.SQL.Clear;
  ZQuery2.SQL.Text:='select * from dog_recive(cast(:piddog as integer),cast(:plpwd as varchar),cast(:pidtr as integer) )';
  ZQuery2.ParamByName('piddog').AsInteger:=idtransact;
  ZQuery2.ParamByName('plpwd').AsString:=Driver.GetPassword(conn);
  ZQuery2.ParamByName('pidtr').AsInteger:=idtransact;
  ZQuery2.ExecSQL;

  Memo1.lines.Add('Получены данные от dog_receive');

  PasswordDlg.ZConnection1.Commit;
 except
 Memo1.lines.Add('Во время транзакции получена ошибка');
 PasswordDlg.ZConnection1.Rollback;
 end;
 Memo1.Lines.Add(_global_str);

end;

end.


Johnmen   (2007-05-10 17:57:00) [2]


>  после всех операций лог видим.

Это о чём?


alexey_mas   (2007-05-10 17:52:00) [3]

аналогично в мемо не выводит.

через глобальную переменную вывожу- но так криво получается - после всех операций лог видим.


procedure NoticeTransfer(arg:Pointer;messages:PChar);cdecl;
       var
       _tmp_str:string;
  begin
       _tmp_str:=Trim(String(messages));
       UniqueString(_tmp_str);
       _global_str:=_global_str+#13+#10+_tmp_str;
      dog_transfer_form.Memo1.lines.Add('test'+_tmp_str);
       
  end;


Johnmen   (2007-05-10 17:40:00) [4]

Пробуй
var
 s : string;
...
procedure NoticeTransfer(arg:Pointer;messages:PChar);cdecl;
...
 s:=messages;
 UniqueString(s);
 dog_transfer_form.Memo1.lines.Add(s);
...


alexey_mas   (2007-05-10 17:23:00) [5]

TZPostgreSQLNoticeProcessor = procedure(arg: Pointer; message: PChar); cdecl;


Johnmen   (2007-05-10 17:08:00) [6]


> alexey_mas ©   (10.05.07 17:00) [13]

Приведи объявление TZPostgreSQLNoticeProcessor.


alexey_mas   (2007-05-10 17:00:00) [7]


> Johnmen ©   (10.05.07 16:21) [10]
>
> Типа того
> var
>  CallBackNoticeTransfer : TZPostgreSQLNoticeProcessor =
> nil;
> ...
> CallBackNoticeTransfer:=@NoticeTransfer;
> ...
> Driver.SetNoticeProcessor(conn,CallBackNoticeTransfer,arg);
>


сделал так.
1)в мемо ничего так и не попадает :(
2)messages всегда пусто теперь при вызове процедуры NoticeTransfer

:(


Виталий Панасенко   (2007-05-10 16:27:00) [8]

"гоню" после праздника..:-)


Виталий Панасенко   (2007-05-10 16:23:00) [9]

А так ?

> procedure NoticeTransfer(arg:Pointer;messages:PChar);cdecl;
>
>        var
>        _tmp_str:string;
>         begin
>        ShowMessage(messages);
>       _tmp_str:=String(messages);
>       dog_transfer_form.Memo1.lines.Add( String(_tmp_str));
>         end;


Johnmen   (2007-05-10 16:21:00) [10]

Типа того
var
 CallBackNoticeTransfer : TZPostgreSQLNoticeProcessor = nil;
...
CallBackNoticeTransfer:=@NoticeTransfer;
...
Driver.SetNoticeProcessor(conn,CallBackNoticeTransfer,arg);


alexey_mas   (2007-05-10 15:54:00) [11]


> > Как можно решить эту проблему?
>
> Убрать cdecl


убрать не могу так как используется С-ная dll
вот здесь 2-м параметром ожидается процедура с директивой cdecl.

Driver.SetNoticeProcessor(conn,NoticeTransfer,arg);

Если убираю ругается на Incompatible types: 'Calling conventions differ'


Johnmen   (2007-05-10 15:40:00) [12]


> Как можно решить эту проблему?

Убрать cdecl

>  я так понимаю что ничего не добавляется потому что на момент
> выполнения метода Memo1.lines.Add парметр уже удален из
> стека.

Нет, ещё нет...
Чтобы это понять, надо знать, что такое строки в D и как организована работа с ними. Для этого надо читать документацию.


alexey_mas   (2007-05-10 15:22:00) [13]


> Johnmen ©  


Как можно решить эту проблему? я так понимаю что ничего не добавляется потому что на момент выполнения метода Memo1.lines.Add парметр уже удален из стека.


Johnmen   (2007-05-10 14:10:00) [14]


> почитал но не понял как применимо то что там написано к моему случаю.

Если не понял, зачем написал?


alexey_mas   (2007-05-10 14:04:00) [15]

почитал но не понял как применимо то что там написано к моему случаю.

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

?


Johnmen   (2007-05-10 13:02:00) [16]

А ты хелп почитай про cdecl.


alexey_mas   (2007-05-10 12:48:00) [17]

ещё один нюанс возник.


procedure NoticeTransfer(arg:Pointer;messages:PChar);cdecl;
       var
       _tmp_str:string;
        begin
       ShowMessage(messages);
      _tmp_str:=String(messages);
      dog_transfer_form.Memo1.lines.Add(_tmp_str);
        end;


В ShowMessage(messages) показывает строку.
Дебагером если смотреть то в переменной  _tmp_str тоже показывает значение.
В мемо ничего не пишется

В чем может быть причина?


alexey_mas   (2007-05-10 11:40:00) [18]

огромное спасибо. получилось


ЮЮ   (2007-05-10 11:35:00) [19]

procedure Tdog_transfer_form.NoticeTransfer(arg:Pointer;messages:PChar);

это не процедура, а метод класса Tdog_transfer_form

regular procedure выглядела бы так:

procedure NoticeTransfer(arg:Pointer;messages:PChar);


Наверх

Титульная страница Поиск, карта сайта Написать письмо