-
February 13th, 2016, 09:56 AM
#1
Wrong function called in DLL
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
"A problem well stated is a problem half solved.” - Charles F. Kettering
-
February 13th, 2016, 10:40 AM
#2
Re: Wrong function called in DLL
Couple things... When using all virtual methods, you do no need dllimport/dllexport. The methods are being called through function pointers or a "jump table" - which we call the v-table. So the code inside the DLL will be called as long as the DLL allocates the object. If the client can allocate the object then you still need import/export.
So the client was re-compiled but the DLL wasn't. The client "see's" that the "jump table" has 3 new entries at the front of the table, but the table in the DLL hasn't changed. The client calls table[3], which is still sample_rate() in the DLL.
The way to add new virtuals while maintaining backwards compatibility is to always add them to the end of the table.
gg
Last edited by Codeplug; February 13th, 2016 at 10:42 AM.
-
February 13th, 2016, 12:36 PM
#3
Re: Wrong function called in DLL
Good explanation Codeplug. Thanks!
"A problem well stated is a problem half solved.” - Charles F. Kettering
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|