top header
com as a better c++term

 

home contents introduction com as a better C++ interfaces classes apartments labs lab setup quizzes
 
previousnext

 
Overview

Let's say you have a C++ class that you would like to publish to the rest of the C++ community. What about a string class? There aren't nearly enough of those about. The class looks like this:

Header file, mystring.h:

class CMyString
{
private:
    char *m_psz;
public:
    CMyString(const char * psz);
    ~CMyString();
    const char*Find(const char *psz);
    int Length();
};

Source file, mystring.cpp:

CMyString::CMyString(const char * psz) : m_psz( new char[psz ? strlen(psz)+1 :1]) {
    if ( psz )
        strcpy(m_psz,psz);
    else
        m_psz[0] = 0;
}
CMyString::~CMyString() {
    delete [] m_psz;
}
const char*CMyString::Find(const char *psz) {
    return strstr(m_psz,psz);
}
int CMyString::Length() {
    return strlen(m_psz);
}

What is the optimal way of packaging this class for use by the rest of the C++ world?

Deployment - Static Linking versus Dynamic Linking
 
Static Linking

One option would be to provide the class in a library that can be statically linked into any target executable client wishing to use it. Just to recap, static linking means that any external references made within the executable client to symbols that exist within the library must be resolved against library code or data at build time. The executable client has to be code and data complete at build time before it can be loaded and executed.

There are three main disadvantages to doing this. All are due to the fact that library code and data has to exist in every executable client that uses it.

  • There is no way for an operating system to detect a library's presence when loading an executable. So there is no way for the operating system to share the library code with any other executable statically linking to the same library. Any executable client that statically links to a library is therefore bigger in memory than it needs to be. Performance will degrade due to page faults. As code and data will live on many different duplicate pages in memory, over time pages must be swapped to disk.
  • Any executable client that statically links to a library is bigger on disk than it needs to be, since the library code has to be contained in every executable so linked.
  • There is no way to upgrade the library code in situ, since the library code is inextricably bound to any executable client that statically links to it. This means bug fixes or functionality upgrades are impossible to achieve in the field.

If you would like to write some code to expose a C++ class from a static link library and to verify the aforementioned assertions, click here.

Dynamic Linking

Another option would be to provide the class in a library that can be dynamically linked into any target executable client wishing to use it. Just to recap, dynamic linking means that any external  references made within the executable client to symbols that exist within the library can be resolved against library code or data at loadtime or runtime. The executable client does not have to be code and data complete at buildtime. It merely contains references to import records that can be used to fix up the references to the library at loadtime of the executable, or it contains no references at all and library code and data can be programmatically loaded and bound at runtime. However, before the executable client can be loaded and/or executed, the library must be successfully located and loaded and all references fixed up. Linkage is merely deferred.

The class definition has to change somewhat.

Header file, mystring.h:

#ifdef MYSTRINGDLL
#define EXPORTORIMPORT _declspec(dllexport)
#else
#define EXPORTORIMPORT _declspec(dllimport)
#endif

class EXPORTORIMPORT CMyString
{
private:
    char *m_psz;
public:
    CMyString(const char * psz);
    ~CMyString();
    const char*Find(const char *psz);
    int Length();
};

As long as the DLL implementation defines the MYSTRINGDLL symbol as

#define MYSTRINGDLL

before the line

#include "mystring.h"

the class will get exported correctly from the DLL and imported correctly into the target executable client.

The advantages to dynamic linking mainly counteract the disadvantages of static linking. All are due to the fact that the library code and data does not have to exist in every executable client that uses it. Each executible client merely needs a reference to the code and data in one single library.

  • There is a way for the operating system to detect a library's presence when loading an executable. So there is a way for the operating system to know to share the library code with another executable client dynamically linking to the same library. An executable client that dynamically links to a library is therefore no bigger in memory than it needs to be.
  • Any executable client that dynamically links to a library is no bigger on disk than it need be, since the library code is not contained in every executable client so linked, merely references to the library code.
  • There is a way to upgrade the library code in situ, since the library code is not inextricably bound to any executable client that dynamically links to it. References are fixed up at loadtime or runtime of the executable client. This means bug fixes or functionality upgrades are possible to achieve in the field. The caveat here is that the public interface of the DLL exported functions does not change (in this case, any of the class method signatures).
  • There need not be any reference to the library in the executable client that makes use of it. The library may be dynamically loaded and bound at run-time, making dynamic discovery of code and data possible.

If you would like to write some code to expose a C++ class from a DLL and to verify the aforementioned assertions, click here.

For a more thorough review of dynamic linking, click here.

Next we will look at how using different C++ compilers complicates matters.


Top of document