Web site:  http://openamiga.org  Open Amiga - Projects20140828 09:22
Content ID:  20
Content title:  library version

Guideline - General programming tips
<- Back to guidelines

Content
    
- Library version checking
- When using static libraries


Library version checking

    
It is prudent to always check if a library is available and that the correct version is available. With the appearance of AmigaOS4.1 some libraries may not be available to 4.0 users or the 4.0 versions might not contain the needed functions. If no version checking is done in these cases then the user might experience crashes or otherwise erroneous behavior.

Here's some sample code for version checking:


#include <stdio.h>

BOOL CheckLibrary (struct Library *base, int version, int revision) {
    if (base->lib_Version > version || (base->lib_Version == version && base->lib_Revision >= revision)) {
        return TRUE;
    }
    return FALSE;
}

int main ( void ) {
    if (!CheckLibrary(LIBRARYBASE, MIN_VERSION, MIN_REVISION)) {
        printf("Newer xyz.library needed! Upgrade ASAP.\n");
        return RETURN_FAIL;
    }
    /* go on with program */
}


    
Replace MIN_VERSION and MIN_REVISION with whatever numbers that are appropriate and LIBRARYBASE with the library base of the library that you are interested in.

If you just want to check version you can do this:


#include <stdio.h>

BOOL CheckLibrary (struct Library *base, int version) {
    if (base->lib_Version >= version) {
        return TRUE;
    }
    return FALSE;
}

int main ( void ) {
    if (!CheckLibrary(LIBRARYBASE, MIN_VERSION)) {
        printf("Newer xyz.library needed! Upgrade ASAP.\n");
        return RETURN_FAIL;
    }
    /* go on with program */
}


    
When retrieving a library base pointer, it must be checked if it is set to NULL. If it is then the program should exit gracefully.


#include <proto/exec.h>

    struct Library *mylibrarybase = IExec->OpenLibrary("my.library",0);

    if(mylibrarybase==NULL)
    {
        printf("Missing my.library! Install and try again.\n");
        return RETURN_FAIL;
    } 


    
or if you want to check multiple locations besides libs:


#include <proto/exec.h>

    struct Library *mylibrarybase = IExec->OpenLibrary("my.library",0);

    if(mylibrarybase==NULL)
    {
        mylibrarybase = IExec->OpenLibrary("PROGDIR:libs/my.library",0);
        {
            if(mylibrarybase==NULL)
            {
                printf("Missing my.library! Install and try again.\n");
                return RETURN_FAIL;
            }
        }
    } 


    
and to put it all together:


#include <proto/exec.h>
#include <stdio.h>

    struct Library *mylibrarybase = IExec->OpenLibrary("my.library",0);

    if(mylibrarybase==NULL)
    {
        mylibrarybase = IExec->OpenLibrary("PROGDIR:libs/my.library",0);
        {
            if(mylibrarybase==NULL)
            {
                printf("Missing my.library! Install and try again.\n");
                return RETURN_FAIL;
            }
        }
    } 

    if(!( CheckLibrary( mylibrarybase, 53, 2 )))
    {
        printf("Your version of my.library is outdated!\n");
        return RETURN_FAIL;
    }

    /* continue with program feeling safe :) */



    
And don't forget to close any libraries that you may have opened prior to exiting the program.


Version checks when OpenLibrary is not used

    
Programs that are compiled against static libraries will not be able to check the library version as described above, as the library opening is done inside the static lib. There is a solution though, and it means using a stand-alone checking system. The function code listed below uses the above techniques to build a function that opens the specified library, check the version/revision and close the library again. By checking the return value from this function, it is possible to determine whether the library in use actually fits the critera required. This check needs to be carried out as "early" as possible in the function to minimise the possibility that library functions may get used. The best approach to this is to include the LibraryOK() function below into your source code, and call it as quickly as possible in the main() function. If the return value is FALSE, the program should exit with a RETURN_FAIL.


#include <proto/exec.h>
#include <dos/dos.h>
BOOL LibraryOK( STRPTR libname, ULONG version, ULONG revision )
{
    struct Library *libBase;
    BOOL ok = FALSE;

    if( libBase = (struct Library *)IExec->OpenLibrary( libname, version ))
    {
        if (libBase->lib_Version > version || (libBase->lib_Version == version && libBase->lib_Revision >= revision)) 
        {
            ok =  TRUE;
        }

        IExec->CloseLibrary( libBase );
    }

    return ok;
}


    
Static libraries open the system shared libraries themselves, the above check should be used in your main() function like so:


#include <stdio.h>

int main( int argc, char **argv )
{
    if(!LibraryOK( "my.library", 53, 2 ))
    {
        printf("my.library is too old, upgrade it and try again\n" );
        return RETURN_FAIL;
    }

    /* the rest of the program is safe to use my.library 53.2 with confidence */

    ...