CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3
  1. #1
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    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

  2. #2
    Join Date
    Nov 2003
    Posts
    1,902

    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.

  3. #3
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    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
  •  





Click Here to Expand Forum to Full Width

Featured