Как назначить ссылку на процедуру (переданную как параметр) в поле записи в Delphi?

Когда я передаю ссылку на процедуру в качестве 9X_object-pascal параметра и хочу присвоить ее другой переменной 9X_delphi ссылки на процедуру (TMyRec.proc), может 9X_object-pascal быть, она хочет вызвать процедуру и присвоить 9X_object-pascal результат... результатом будет 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 

2
0
1
Общее количество ответов: 1

Ответ #1

Ответ на вопрос: Как назначить ссылку на процедуру (переданную как параметр) в поле записи в Delphi?

Компилятор не должен пытаться вызывать процедуру, поскольку 9X_object-pascal ей не передается входной параметр.

Я подозреваю, что 9X_delphi реальная проблема заключается в том, что вы используете 9X_object-pascal GetMem(), поскольку она не инициализирует поля записи 9X_object-pascal нулями. Итак, вы пытаетесь присвоить pMR^.proc, когда 9X_delphi оно содержит неопределенное значение, которое, скорее 9X_delphi всего, не nil. А так как TMyProc под капотом является 9X_delphi типом интерфейса с подсчетом ссылок, компилятор 9X_delphi пытается Release() "старый" интерфейс и 9X_object-pascal падает.

pMR^.proc должно быть nil, прежде чем вы его 9X_object-pascal назначите. Попробуйте вместо этого использовать 9X_delphi AllocMem(), так как это приведет к обнулению выделенной 9X_delphi памяти. Или лучше используйте вместо этого 9X_object-pascal New().

Кроме того, при использовании GetMem() или AllocMem() вам 9X_object-pascal необходимо вручную завершить запись перед 9X_delphi освобождением памяти, чтобы счетчик ссылок 9X_object-pascal 'proc' правильно уменьшался для освобождения 9X_object-pascal анонимной процедуры. Вам не нужно беспокоиться 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; 

11
0