API Development KitVersion: 15

API Compatibility

Summary: This document discusses issues related to add-on compatibility.

  1. Introduction
  2. API compatibility
    1. Interface
    2. Library

0. Introduction

For a good summary on (C++) compatibility, see this page from the KDE site. We'll use the terms binary and source compatible the way they were defined on that page. The first type is superior (and of course, more valuable) from the developer's point of view, as this doesn't require any work from your side.

With the introduction of ArchiCAD 8, the previous binary compatibility of add-ons was lost (i.e. ArchiCAD's ability to load and run add-ons compiled for previous versions -- namely, version 6.0, 6.5 and 7.0). On one hand, this was due to the modernization of the registration mechanism, and on the other hand due to the enormous effort which this kind of compatibility would have required.

Between ArchiCAD 8, 8.1, 9, and 10 we do not ensure binary compatibility because of the interface changes of several modules (such as InputOutput, or GSRoot), so add-ons compiled with 4.x DevKits cannot be loaded in ArchiCAD 8.1 or ArchiCAD 10. The add-ons developed for ArchiCAD 8 or 8.1 must be re-compiled with this DevKit in order to enable them to run with ArchiCAD 10.

This document explains what compatibility means from the add-on developer's point, and what you can do about it.

1. API compatibility

Below we'll take a look at the different areas of the API where this may be an issue.

1.a Interface

By definition, an interface to a library can fulfill only source level compatibility. This means that the functionality of the API can only be extended with new functions, and the old functions shouldn't change.

The API (by itself) provides only a C interface (we have to admit this in not really true any more from ArchiCAD 8). This C interface is easier to keep source and binary compatible, because the different compilers generate the same code for the same interface. Also, the ACAP_STAT.lib contains a function table, where we left many places for the introduction of new functions.

If an old function is not relevant any more, then it should still sit there and mimic the behavior it provided in previous versions. This may require serious internal programming effort, as we would have to implement the old functionality internally over a newer set of internal interfaces. If the old functionality is still viable, just requires extra parameters to provide the functionality available in the actual version of ArchiCAD, then we can introduce a new function (much like the ...Ex functions in the Windows platform SDK). In the C interface, in the past we used the filler places in the function table to store the addresses of these functions.

In the C++ world, the (virtual) function table is generated by the compiler, and no filler 'place' exists. So, if we introduce a new function in this interface, then all code linked to this C++ library would suddenly become unusable, and your add-on would not be loaded by ArchiCAD.

Recommendation: stick to the C interface if you want to stay binary compatible. This also applies to other modules, for example the file/folder dialogs in the DG module. There are certain places where you can't achieve this (most notably the InputOutput module); but then expect to compile your add-on as a new (maintenance) version ArchiCAD reaches your market.

Featuring API 10  Note that the CIO interface of the InputOutput module is not supported any more, use the C++ IO interface instead.

1.b Library

The API Development Kit contains two versions of the API library, ACAP_STAT.lib and ACAP_DLL.apx. In most cases you link your code to the static library, which provides the main entry points to the add-on (DLL/shared library), and builds up an internal function table where it stores all the addresses of the available functions. This static library also provides a version number for the API interface of ArchiCAD, which can be used internally to provide the expected behavior of the application for an add-on if a subsequent maintenance release appears.

The other ACAP_DLL.apx enables you to do the initialization yourself. This way you can build up your own function table, and you also have more control over the initialization and termination of your DLL. This is the easiest way to stay binary compatible with the API itself, though it requires a lot more work from your side. See the DLL_Test example.

A very important point in the version controlling process is the obligatory CheckEnvironment function:

// -----------------------------------------------------------------------------
// Dependency definitions
// -----------------------------------------------------------------------------
API_AddonType    __ACENV_CALL    CheckEnvironment (API_EnvirParams* envir)
    // for tool-type add-ons: skip if not in ArchiCAD
    if (envir->serverInfo.serverApplication != APIAppl_ArchiCADID)
        return APIAddon_DontRegister;

    GSResModule saveResModule = ACAPI_UseOwnResModule ();
    ACAPI_Resource_GetLocStr (envir->, 32000, 1);
    ACAPI_Resource_GetLocStr (envir->addOnInfo.description, 32000, 2);
    ACAPI_ResetResModule (saveResModule);

    return APIAddon_Normal;
}        // CheckEnvironment

The API_EnvirParams structure contains the main and the maintenance version of the server application. Based on this information your add-on can decide whether it wants to run in the current server application. For example, a bug has been corrected in the R2/v2 version of ArchiCAD 8.1, which prevented the operation of your add-on in 8.1 R1/v1. In this case you can test the server application's version in the CheckEnvironment () function, and return APIAddon_DontRegister if envir->serverInfo.releaseVersion < 2.