Как назначить ссылку на процедуру (переданную как параметр) в поле записи в Delphi?
Когда я передаю ссылку на процедуру в качестве 9X_delphi параметра и хочу присвоить ее другой переменной 9X_delphi ссылки на процедуру (TMyRec.proc), может 9X_object-pascal быть, она хочет вызвать процедуру и присвоить 9X_delphi результат... результатом будет GPF. Как 9X_delphi я могу назначить параметр, переданный proc 9X_delphi ref, другому proc ref?
Пример: он просто 9X_delphi играет с заданием. Нет никаких реальных 9X_delphi задач, назначенных как procs.
unit5.pas:
unit Unit5;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm5 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form5: TForm5;
implementation
{$R *.dfm}
type
TMyProc = reference to procedure ( i_ : integer );
PMyRec = ^TMyRec;
TMyRec = packed record
i : integer;
proc : TMyProc;
end;
procedure TForm5.Button1Click(Sender: TObject);
procedure createMyRec( i_ : integer; const proc_ : TMyProc );
var
pMR : PMyRec;
begin
getMem( pMR, sizeOf( TMyRec ) );
try
pMR^.i := i_;
pMR^.proc := proc_; // <--- GPF occures here
finally
FreeMem( pMR );
end;
end;
begin
createMyRec( 1, procedure ( i_ : integer ) begin end );
createMyRec( 2, procedure ( i_ : integer ) begin end );
end;
end.
unit5.dfm:
object Form5: TForm5
Left = 0
Top = 0
Caption = 'Form5'
ClientHeight = 441
ClientWidth = 624
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = 'Segoe UI'
Font.Style = []
TextHeight = 15
object Button1: TButton
Left = 200
Top = 176
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
end
Ответ #1
Ответ на вопрос: Как назначить ссылку на процедуру (переданную как параметр) в поле записи в Delphi?
Компилятор не должен пытаться вызывать процедуру, поскольку 9X_object-pascal ей не передается входной параметр.
Я подозреваю, что 9X_delphi реальная проблема заключается в том, что вы используете 9X_object-pascal GetMem()
, поскольку она не инициализирует поля записи 9X_delphi нулями. Итак, вы пытаетесь присвоить pMR^.proc
, когда 9X_delphi оно содержит неопределенное значение, которое, скорее 9X_delphi всего, не nil
. А так как TMyProc
под капотом является 9X_delphi типом интерфейса с подсчетом ссылок, компилятор 9X_object-pascal пытается Release()
"старый" интерфейс и 9X_object-pascal падает.
pMR^.proc
должно быть nil
, прежде чем вы его 9X_delphi назначите. Попробуйте вместо этого использовать 9X_object-pascal AllocMem()
, так как это приведет к обнулению выделенной 9X_object-pascal памяти. Или лучше используйте вместо этого 9X_delphi New()
.
Кроме того, при использовании GetMem()
или AllocMem()
вам 9X_object-pascal необходимо вручную завершить запись перед 9X_object-pascal освобождением памяти, чтобы счетчик ссылок 9X_delphi 'proc' правильно уменьшался для освобождения 9X_delphi анонимной процедуры. Вам не нужно беспокоиться 9X_delphi об этом с New()
, так как Dispose()
завершит запись для 9X_delphi вас.
Попробуйте это:
procedure createMyRec( i_ : integer; const proc_ : TMyProc );
var
pMR : PMyRec;
begin
pMR := PMyRec( AllocMem( SizeOf( TMyRec ) ) );
try
pMR^.i := i_;
pMR^.proc := proc_;
finally
Finalize( pMR^ );
FreeMem( pMR );
end;
end;
Или:
procedure createMyRec( i_ : integer; const proc_ : TMyProc );
var
pMR : PMyRec;
begin
New( pMR );
try
pMR^.i := i_;
pMR^.proc := proc_;
finally
Dispose( pMR );
end;
end;
-
6
-
10
-
15
-
14
-
4
-
10
-
6
-
18
-
3
-
5
-
9
-
3
-
8
-
3
-
1
-
3
-
7
-
3
-
3
-
4
-
4
-
11
-
1
-
9
-
2
-
6
-
6
-
3
-
7
-
4
-
4
-
6
-
1
-
2
-
2
-
7
-
4
-
12
-
5
-
2
-
2
-
4
-
7
-
3
-
5
-
3
-
4
-
7
-
4
-
3