Kryvich 165 Posted November 13, 2018 I can do it without RTTI, but get a compiler error when using RTTI: procedure TForm1.Button1Click(Sender: TObject); var ctx: TRttiContext; rt: TRttiType; fld: TRttiField; proc: TWndMethod; begin proc := TabSet1.WindowProc; // Compiles and works OK without RTTI ctx := TRttiContext.Create; try rt := ctx.GetType(TControl); fld := rt.GetField('FWindowProc'); ShowMessage(fld.GetValue(TabSet1).TypeInfo.Name); // 'TWndMethod' if fld.GetValue(TabSet1).IsType<TWndMethod> then // True proc := fld.GetValue(TabSet1).AsType<TWndMethod>; // E2010 Incompatible types: 'procedure, untyped pointer or untyped parameter' and 'TWndMethod' finally ctx.Free; end; end; Any suggestions? Share this post Link to post
Lars Fosdal 1792 Posted November 13, 2018 what if you first extract it as a pointer, and then cast the pointer to TWndMethod? 1 Share this post Link to post
Kryvich 165 Posted November 13, 2018 (edited) But will this be the right solution? These types have different sizes (tested for Win32): if SizeOf(Pointer) <> SizeOf(TWndMethod) then ShowMessage('No way.'); // 4 <> 8 I tried this: var i64: UInt64; ... i64 := fld.GetValue(TabSet1).AsUInt64; proc := TWndMethod(i64); But get Exception EInvalidCast 'Invalid class typecast' for GetValue.AsUInt64. Update. I did it like this: var p: Pointer; ... p := fld.GetValue(TabSet1).GetReferenceToRawData; proc := TWndMethod(p^); Thanks @Lars Fosdal for the hint! Edited November 13, 2018 by Kryvich 1 Share this post Link to post
Remy Lebeau 1394 Posted February 8, 2019 Remember that a pointer-to-class-method, such as TWndMethod, is represented by the RTL's TMethod record, which contains 2 pointers - a pointer to an object instance, and a pointer to the method code. TValue.AsUInt64 fails for a TWndMethod value because TValue supports only conversions that the compiler natively supports implicitly, and you can't implicitly assign a TMethod to a UInt64 and vice versa. That also explains why the TValue.GetReferenceToRawData() approach works - it is just returning a raw pointer to the actual TControl.FWndMethod instance member, which is then dereferenced when being assigned to the local TWndMethod variable. So, no conversion occurs. Now, why TValue.AsType<TWndMethod> fails to compile, I don't know. Sounds like a bug. Share this post Link to post
Stefan Glienke 2002 Posted February 8, 2019 6 hours ago, Remy Lebeau said: Now, why TValue.AsType<TWndMethod> fails to compile, I don't know. Sounds like a bug. It probably is lacking the `()` there which it sometimes needs when invoking a method that returns an invokable type. 3 Share this post Link to post
Kryvich 165 Posted February 8, 2019 @Stefan Glienke Just checked your suggestion, brilliantly! proc := fld.GetValue(TabSet1).AsType<TWndMethod>(); No compiler errors. 2 Share this post Link to post