We value your input! Please participate in Archicad 28 Home Screen and Tooltips/Quick Tutorials survey
on 2024-04-29 01:21 PM
This document discusses issues related to add-on compatibility.
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.
As Archicad and its API is written in C++, we do not provide binary compatibility between main Archicad versions because of the interface changes of several modules, so add-ons compiled with older DevKits cannot be loaded in a newer Archicad main version. Add-ons developed for an earlier Archicad must be re-compiled with the new DevKit in order to enable them to run with current Archicad.
This document explains what compatibility means from the add-on developer's point, and what you can do about it.
By definition, an interface to a library can only provide 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 mostly a C interface. This C-like 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 add many placeholders to be able to introduce new functions in minor Archicad updates.
If an old function is not relevant any more, then it should still sit there and mimic the behavior it provided in previous versions, as long as this is feasible. 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.
The API Development Kit contains the API as a static library, ACAP_STAT.lib. As you link your code to the static library, it provides the main entry points to the add-on (DLL/bundle), 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.
A very important point in the version controlling process is the obligatory CheckEnvironment() function:
// -----------------------------------------------------------------------------
// Dependency definitions
// -----------------------------------------------------------------------------
API_AddonType __ACENV_CALL CheckEnvironment (API_EnvirParams* envir)
{
RSGetIndString (&envir->addOnInfo.name, 32000, 1, ACAPI_GetOwnResModule ());
RSGetIndString (&envir->addOnInfo.description, 32000, 2, ACAPI_GetOwnResModule ());
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 maintenance update of Archicad, which prevented the operation of your add-on in the original major release. In this case you can test the server application's version in the CheckEnvironment() function, and return APIAddon_DontRegister if envir->serverInfo.releaseVersion doesn't match your need.