Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.09.02;
Скачать: CL | DM;

Вниз

передача процедуры в процедуре   Найти похожие ветки 

 
alexey_mas ©   (2007-05-10 11:23) [0]

Добрый день!

помогите определить правильно процедуру в дельфях.
Использую компоненты 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;


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

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


 
ЮЮ ©   (2007-05-10 11:35) [1]

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

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

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

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


 
alexey_mas ©   (2007-05-10 11:40) [2]

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


 
alexey_mas ©   (2007-05-10 12:48) [3]

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


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 тоже показывает значение.
В мемо ничего не пишется

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


 
Johnmen ©   (2007-05-10 13:02) [4]

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


 
alexey_mas ©   (2007-05-10 14:04) [5]

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

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

?


 
Johnmen ©   (2007-05-10 14:10) [6]


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

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


 
alexey_mas ©   (2007-05-10 15:22) [7]


> Johnmen ©  


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


 
Johnmen ©   (2007-05-10 15:40) [8]


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

Убрать cdecl

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

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


 
alexey_mas ©   (2007-05-10 15:54) [9]


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


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

Driver.SetNoticeProcessor(conn,NoticeTransfer,arg);

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


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

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


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

А так ?

> 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;


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

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


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


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


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

:(


 
Johnmen ©   (2007-05-10 17:08) [14]


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

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


 
alexey_mas ©   (2007-05-10 17:23) [15]

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


 
Johnmen ©   (2007-05-10 17:40) [16]

Пробуй
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:52) [17]

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

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


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:57) [18]


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

Это о чём?


 
alexey_mas ©   (2007-05-10 18:08) [19]

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.




Страницы: 1 вся ветка

Текущий архив: 2007.09.02;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.024 c
1-1182412276
ChaoX
2007-06-21 11:51
2007.09.02
Как запустить форму из пакета?


15-1186059055
Dib@zol
2007-08-02 16:50
2007.09.02
Fraps must die


15-1186253150
palva
2007-08-04 22:45
2007.09.02
что для программиста - развлечение, то для ламера - смерть


2-1186607112
Miroving
2007-08-09 01:05
2007.09.02
Как установить некоторую форму поверх других


4-1173535913
mentor-m
2007-03-10 17:11
2007.09.02
Командная строка