Variant Invoke and RTTI

I was “spring cleaning” my temporary project directory on my hard drive today and I found a half-finished implementation of a dynamic dispatch for objects based on new RTTI (Delphi 2010+). I spent some time and fixed the last issues I had and now I think it’s ready to be published.

All the code is enclosed in a single unit (there’s not that much code actually) that exposes one function called “AsDynamic“. This method expects a normal non-nil object, a lifetime management flag and returns a custom Variant value.  The Variant can be used later on to dynamically invoke any method/property on that object.

The following example shows a wrapped TStringList object:

var
  LVarList: Variant;
begin
  { Create a new String List and wrap it into a Variant. By default the Variant will also take care about freeing the object. }
  LVarList := AsDynamic(TStringList.Create);

  { Add two strings to the string list. Note that Add() is called dynamically here. }
  LVarList.Add('Hello World!');
  LVarList.Add('Cool string');

  { Make the list sorted (also dynamically) }
  LVarList.Sorted := True;

  { ... And finally write the contents of the list }
  WriteLn(LVarList.Text);
end.

I don’t see any practical uses this code but it’s good for learning purposes. It can also be a simplified way of treating the cases when one has to execute the same code on classes that do not share a common ancestor or cannot implement an interface.

Just a quick note on what you can see inside the unit:

  • Defining a custom Variant type by extending TInvokeableVariantType and providing the proper support code.
  • An intermediate object and an interface that contain the wrapped object and RTTI structures needed for dynamic invoke. The custom Variant type carries over this object (actually an interface reference).
  • TValue to Variant and Variant to TValue conversion. Since the dynamic dispatch uses variants for arguments a conversion is required in both directions. This is simple in most cases but rather complicated for var and out parameters.

Note that dynamic dispatch as implemented by Delphi has quite a few restriction in what types are allowed and how exactly those values are passed to the invoked methods. For example literals are passed by value and variables are passed by reference (not always!). This is due to the nature of “not knowing” what exactly the method behind expects. As an example, you cannot pass a String by reference while a WideString variable is always passed by reference.

The code can be found here: Dynamic Object Dispatch (2301)

7 Responses to 'Variant Invoke and RTTI'

  1. It sound good but the RTTI is still quite limited and will not allow (without ugly runtime code generation) full AOP-like wizardry. The guys from Spring for Delphi will absolutely benefit for such features.

    My dream is to to be able to easily create in Delphi (like in Java, .NET …etc) the following “artifacts”:
    – proxies for interfaces and non-final classes
    – easy mocks
    – easy BDD
    – AOP aspects
    – easy/on-demand dynamic loading/unloading for packages (sort of class loading but at the “assembly” level as done in .NET)

    Is definitely true that Delphi (even being native !) had closures before Java (due to 2012/Java 8) but will be good to have some additional feature-stealing in Delphi from other modern languages.

    I’m not a fun of LINQ type of features … but looking into Scala (traits, extended generics/self-types, pattern matching, actors, easy DSLs, parallel support) … should give anybody a clear look of what I mean. BTW: LINQ type of features can be implemented as internal DSLs.

    Hopefully the compiler guys (Barry & co) are looking into these also to benefit long-term the Delphinians arena :)

    • alex says:

      Most of the features you would like cannot be easily implemented in a native language such as Delphi and even if they can it would take a completely new compiler architecture. So for the time being we can only play with what we got, trying to “defeat” the system :)

  2. Stefan says:

    Unfortunatly the majority of delphi developers (at least from my experience) are not very interested in those kind of features. :(

  3. Any chance of a DeHL 0.85 build soon ?

    No major changes..

    Just the DeHL collection section removed, with any Collection.Base etc usage to now use the Collections 1.1.1 ?

    Just makes things a little cleaner not having 2 sets of collections included.

    Thanks
    Andrew

  4. A. Bouchez says:

    Interesting approach. I use something similar for access of column values of a SQL query in our classes.
    The DispInvoke procedure default implementation is quite slow.
    If you want to have your aVariant.Method resolution made faster, you can see what I’ve written at http://blog.synopse.info/post/2011/07/01/Faster-variant-late-binding

    • alex says:

      Interesting read indeed, though I was just curious about the dynamism itself rather than speed. I wasn’t planning on actually using it anywhere except a demo.

  5. Hassan says:

    You share interesting things here. I think that your website can go viral
    easily, but you must give it initial boost and i know how to do it, just search in google for – wcnu
    traffic increase

Leave a Reply to Dev{eloper} Stonez Cancel reply

Your email address will not be published.