Join the Discussion
"Post your views, comments, questions and doubts to this article."
Article written by Curtis Socha, brought to you by Zarko Gajic.
Oh, the glory of leadership!
The act of moving data across program boundaries is called Marshaling. When you are using a DLL on your local machine, the objects and functions you create are inside the address space of the calling program. Therefore, you dont really have to worry about marshaling any data because it is already within your program address space. You are within program boundaries. This all changes when we start talking about out-of-process servers like automation and DCom of course.
Automation servers reside in their own program address space, and DCom objects are obviously not even on the same computer. In this situation, marshaling data becomes necessary because you usually cannot read or write to a variable declared in a different address space. Fortunately for us, Windows will take care of a good part of the marshaling behind the scenes. All that Windows asks is that you use data types that it knows how to marshal. Sounds simple, eh?
Simple as it may sound, we run into another big problem when it comes to marshaling. Records and arrays. How do we move record structures to and from Com objects? How do you move an array of structures? The answer is Variant Arrays.
Hint: To see a list of data types that can be automatically marshaled, view the listing from the 4th class. Any types that have Automation set to "Yes" are automatically marshaled.
All of this hard earned knowledge will finally be put to use, by creating ...
Behold the power of Variants
As you have probably already figured out, a variant can hold just about any type of data. Variants play a crucial role in programming COM programming. They are considered to be the equivalent of the safe arrays used for OLE Automation. Although using variants will severely impede machine performance, they allow you to do things you normally could not do without considerable effort.
Variant Reference Page
The Variant Reference Page is a compilation of variant information I gathered after spending 2 hours exploring System.Pas. It is worth delving into this unit for a few hours to see how the masters at Borland encapsulated the entire world of variants into just a handful of functions and procedures. Unfortunately, they did not make them easy to find in the Delphi Help. In order to make your life easier, I built this reference page.
VarType (Value) Contents of Variant
varEmpty ($0000) The variant is Unassigned
varNull ($0001) The variant is Null
varSmallint ($0002) 16-bit signed integer (type Smallint).
varInteger ($0003) 32-bit signed integer (type Integer).
varSingle ($0004) Single-precision floating-point value (type Single).
varDouble ($0005) Double-precision floating-point value (type Double).
varCurrency ($0006) Currency floating-point (type Currency). Default floats are type currency.
varDate ($0007) Date and time value (type TDateTime).
varOLEStr ($0008) Reference to a dynamically allocated UNICODE string. (PWideChar)
varDispatch ($0009) Reference to an Automation object (an IDispatch interface pointer).
varError ($000A) Operating system error code. (type LongWord)
varBoolean ($000B) 16-bit boolean (type WordBool).
varVariant ($000C) Holds a 16 byte variant. Variants can contain variants!
varUnknown ($000D) Reference to an unknown COM object (IUnknown interface pointer).
varByte ($0011) 8-bit unsigned integer (type Byte).
varStrArg ($0048) ? I cannot figure out what this is for.
varString ($0100) Reference to a dynamically allocated Pascal string (type AnsiString).
varAny ($0101) A pointer. Use only to pass to Corba functions.
varTypeMask ($0FFF) Bit mask for extracting type code.
varArray ($2000) Bit indicating variant array. (type PVarArray)
varByRef ($4000) Bit indicating variant contains a reference (rather than a value).
Methood #13#10 Usage #13#10 Description
V := VarArrayCreate([0, 5, 0, 3], varInteger);
Creates an array[0..5, 0..3] of integer.
MyInt := VarArrayDimCount(V);
//Returns the dimensions if is a variant array
MyHighBound := VarArrayHighBound(V, 1);
Returns high boundary of 1st dimension.
V := VarArrayOf([1, Hello Word, 13.23);
Creates a filled array[0..2] of variant.
MyArrayPtr := VarArrayLock (V);
Locks the v array into standard Delphi type
MyLowBound := VarArrayLowBound(V, 1);
Returns low boundary of the 1st dimension.
Resizes V arrays rightmost dimension to 5.
Pass reference of variant array to Win API.
Unlocks a variant array.
V := VarAsType(V, varString);
will convert V into a varString VarType
Sets V to unassigned.
V := VarFromDateTime(MyDateTime);
Converts a TDateTime to a variant type.
if VarIsArray(V) then showmessage(V is Array!);
Tests to see if a variant is of varArray.
if VarIsEmpty(V) then ShowMessage(Empty!);
Tests to see if set to varEmpty or if it is varDispatch / varUnknown and is nil.
if VarIsNull(V) then ShowMessage(Its Null!);
Tests to see if a variant is set to varNull
MyDateTime := VarToDateTime(V);
Converts variant to a TDateTime type.
Converts Variant to Str. Error checks it 1st.
SomeInt := VarType(V) and varTypeMask;
Will return the VarType of the variant
Note 1: Look in System.Pas for variant support functions not listed in the Delphi Help!
Note 2: V is declared as a type Variant.
Note 3: Use OLEVariant when you want to use only COM-Compatible types.
Next page > Using Variants and Variant Arrays > Page 1, 2, 3
An Introduction to COM Programming with Delphi: Table of Content
<< Previous Lesson (4): A Com Object walk-a-bout. A Class Factory tour. Our first true COM Object program.
>> Last Lesson (6): Let's see how to make your first Type Library using Delphi.