delphiclassvmt

How to check if passed argument is class?


I have function (written in Delphi 7, 32-bit):

Function GetVMTAddr(var C): Integer;
Begin
  Result := Integer(C);
  Try
    PVmt(Result)^.SelfPtr := PVmt(C)^.SelfPtr;
  Except
    Result := 0;
  End;
End;

Which returns VMT Address (I think it is VMT, I'm not sure) and checks if parameter is an object (by try...except, which is imho poor solution).
I have two questions:
1) Is this really VMT address or I'm wrong?
2) Is there any better solution to check that parameter is an object?


Solution

  • The argument C will hold a VMT address if what you pass to it is a class reference (a.k.a. a metaclass).

    The condition you check in the function is useless. It checks whether a certain region of memory is writable, and that's all. If you were checking whether the SelfPtr field was equal to the value itself, then you'd be closer. Something like this:

    if PVmt(C).SelfPtr = C then
      Result := C;
    

    What you're asking is very similar to a question asked here a few years ago, where someone wanted to know how to detect the type of a variable. As I explained then, if you've gotten to the point where you think you need to use this code, you're already in trouble. Go back and change your design so that you can know whether you have a class reference or an object reference instead of having to guess.

    If you really have to guess, then you can try using the functions provided by the JCL, IsClass and IsObject. They do the same guessing that your code attempts to use, but they do it right.