![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
передача процедуры в процедуре [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);