Delphi 2006中如何赋值存储函数指针而非触发调用?
Delphi 2006 函数指针转普通指针的问题
问题场景
我声明了如下函数指针类型:
THandleTableCellEdit = function(InitValue, FileNum, IENS, FieldNum : string; GridInfo : TGridInfo; var Changed, CanSelect : boolean; ExtraInfo : string = ''; ExtraInfoSL : TStringList = nil; Fields : string = ''; Identifier : string = '') : string;
同时有一个匹配该类型的函数:
function HandlePtrEdit(InitValue, FileNum, IENS, FieldNum : string; GridInfo : TGridInfo; var Changed, CanSelect : boolean; ExtraInfo : string; ExtraInfoSL : TStringList; Fields : string; Identifier : string) : string;
我需要把这个函数指针通过TStringList的AddObject方法和名称关联存储,但在赋值时遇到编译错误:
procedure TfrmTopicICDLinker.btnEditSectionClick(Sender: TObject); var frmGUIEditFMFile: TfrmGUIEditFMFile; i : integer; Data, IEN : string; GridInfo : TGridInfo; //owned elsewhere Handler : THandleTableCellEdit; HandlerPtr : Pointer; begin i := lbSection.ItemIndex; if i < 0 then exit; Data := lbSection.Items[i]; IEN := piece(Data,'^',4); frmGUIEditFMFile := TfrmGUIEditFMFile.Create(Self); try frmGUIEditFMFile.SetGridsToShow([integer(tsgAdvanced)]); frmGUIEditFMFile.PrepForm('22753', IEN+',', IntToStr(User.DUZ)); GridInfo := frmGUIEditFMFile.GridInfo(tsgAdvanced); GridInfo.IdentifierCode := 'DO SUBRECID^TMGTIUT3(DIC,Y,+$GET(DIFILE))'; Handler := HandlePtrEdit; HandlerPtr := Handler; // <---------- 此处报错:实际参数不足 GridInfo.CustomPtrFieldEditors.AddObject('80', HandlerPtr); frmGUIEditFMFile.ShowModal; finally frmGUIEditFMFile.Free; end; end;
编译器误将HandlerPtr := Handler;解析为调用函数指针,导致参数不足的报错。尝试过多种强制转换方式均无效,需要解决如何将函数指针视为普通指针处理,以及更优的实现方案(使用Delphi 2006,无法使用模板/类型化列表)。
解决方法
1. 用@运算符取函数指针地址
直接通过@获取函数指针的内存地址,赋值给普通指针变量:
// 方式一:取中间变量的地址 HandlerPtr := @Handler; // 方式二:跳过中间变量,直接取函数的地址 HandlerPtr := @HandlePtrEdit;
2. 显式类型转换
如果@运算符方式不生效,可尝试显式将函数指针转换为Pointer类型:
HandlerPtr := Pointer(Handler); // 或者直接转换函数地址 HandlerPtr := Pointer(@HandlePtrEdit);
3. 更优的存储方案
利用TStringList的AddObject方法直接存储函数指针(Delphi中TObject本质是指针类型,可直接接收函数地址):
// 存储时 GridInfo.CustomPtrFieldEditors.AddObject('80', TObject(@HandlePtrEdit)); // 取出使用时,转换回原函数指针类型 var EditHandler: THandleTableCellEdit; begin EditHandler := THandleTableCellEdit(GridInfo.CustomPtrFieldEditors.Objects[Index]); // 调用函数 Result := EditHandler(InitValue, FileNum, IENS, FieldNum, GridInfo, Changed, CanSelect, ...); end;
原理说明
在Delphi中,函数指针变量既可以当作指针使用,也可以直接当作函数调用。当你直接赋值HandlerPtr := Handler时,编译器会优先解析为函数调用(因为函数指针的调用语法就是直接写变量名加参数),因此需要通过@运算符明确告诉编译器要取的是指针地址,而非调用函数。
内容的提问来源于stack exchange,提问作者kdtop
相关产品推荐
相关产品推荐

