Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2007.09.02;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.043 c
2-1186721351
Tomy Versety
2007-08-10 08:49
2007.09.02
Руководство по пользованию


2-1186648638
waif
2007-08-09 12:37
2007.09.02
ADO + access


3-1178790763
Godness
2007-05-10 13:52
2007.09.02
A query with LOB s requires OCI8 mode, but OCI7 mode is used


2-1186593827
Sonia
2007-08-08 21:23
2007.09.02
Проблема с настройками клиента Oracle (а может еще чего-то)


9-1158666426
Nic
2006-09-19 15:47
2007.09.02
Нет диска к книге





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский