Fog Creek Software
Discussion Board




HOWTO: Manage versioned data structures for API

I have inherited a legacy API (exported from DLLs written in C/C++) that only used atomic data types (int,short,long,char*, etc) because the designer (a newbie) didn't know how to pass C structs when calling the API from Visual Basic.  :: I know what your thinking.. don't ask! ::

The API has evolved into our so called "Platform SDK" and the need for better API interface design is needed.

I have already been forced to create new "***Ex()" versions of our existing APIs becuase changing the interface signature of an existing API would break all backward compatibility with existing SDK users!

As our platform features expand and increase, i need to start making our API's more flexible to future changes and allow for better versioning support.

The only flexible way I know of is to start using struct pointers as parameters to the API, but this leads to the issue of versioning C structs that change size over time as versions and platform features change.  Similar to the Windows Platform API'S change that happen over time.

NOTE: COM objects with versioned interfaces is NOT an option for me at this stage in the game!

API's from Microsoft Platform SDK often use data strutures that contain the following members
  1. DWORD dwSize
  2. WORD wVersion
  3. both 1 and 2

Is this the most/best _flexible_ way to version data structures. or are there simpler ways of achieving this.

Can anyone point me to public source code that shows how to code and manage many different versions of the same structure over time.

What if I was forced to change an API and had to create a "minor-version" change to an API C struct in a branched release for a patch build.

example MSFT versioned structure used with the COMMs API: from winbase.h
typedef struct _COMMCONFIG {
    DWORD dwSize;              /* Size of the entire struct */
    WORD wVersion;              /* version of the structure */
    WORD wReserved;            /* alignment */
    DCB dcb;                    /* device control block */
    DWORD dwProviderSubType;    /* ordinal value for identifying
                                  provider-defined data structure format*/
    DWORD dwProviderOffset;    /* Specifies the offset of provider specific
                                  data field in bytes from the start */
    DWORD dwProviderSize;      /* size of the provider-specific data field */
    WCHAR wcProviderData[1];    /* provider-specific data */
} COMMCONFIG,*LPCOMMCONFIG;

Heston Holtmann
Wednesday, July 23, 2003

Is this the "best" way?.  Well, that is like asking is it the best car...  OTOH, MS has a pretty good track record on versioning and patching.  (I do wonder if anything over zero is really a good patch record, but I digress)

It is a very common method because it is fairly easy to maintain and control.  As for "minor" releases of the API, I would believe there is no such thing.  If you change an  API, for external consumption, someone has to notice or why bother?  If they notice, it is not minor to them. 

I think you are on the right track. 

BigRoy
Wednesday, July 23, 2003

*  Recent Topics

*  Fog Creek Home