Keep in mind that LIBARDOUR_API is defined as dllexport (for the DLL) or dllimport (for the main app). This stuff is known to both the app and a DLL that it uses:-

Code:
class LIBARDOUR_API BaseClass {
public:

    // Various member functions (mostly pure virtual)

    virtual std::string  device_name () const = 0;
    virtual std::string  input_device_name () const { return std::string(); }
    virtual std::string  output_device_name () const { return std::string(); }
    virtual float        sample_rate () const = 0;
    virtual uint32_t     buffer_size () const = 0;
};
This stuff is known only to the DLL:-

Code:
class LIBARDOUR_API DerivedClass : public BaseClass
{
public:

    virtual std::string device_name () const;
    virtual float       sample_rate () const;
    virtual uint32_t    buffer_size () const;

};
To get the relevant device name, my app does this:-

Code:
std::string name = _backend->device_name();

// where _backend is a boost::shared_ptr (assume it got initialized okay)
boost::shared_ptr<BaseClass> _backend;
Okay - so far, everything works fine. Now somebody added a few extra functions to the base class (but without rebuilding the DLL)

Code:
class LIBARDOUR_API BaseClass {
public:

    // Various member functions (mostly pure virtual

    // 3 x newly added functions
    virtual bool can_use_buffered_io () { return false; }
    virtual void set_use_buffered_io (bool) { }
    virtual bool get_use_buffered_io () { return false; }

    virtual std::string  device_name () const = 0;
    virtual std::string  input_device_name () const { return std::string(); }
    virtual std::string  output_device_name () const { return std::string(); }
    virtual float        sample_rate () const = 0;
    virtual uint32_t     buffer_size () const = 0;
};
To my surprise, if the app tries to call device_name() in the DLL, it now actually calls the wrong function. It calls sample_rate(). What's going on here? I thought the DLL handling had mechanisms to prevent this kind of thing from happening