Thread: How to solve warnings that appear when building my DLL...

  1. #1
    Registered User starcatcher's Avatar
    Join Date
    Feb 2008
    Location
    Australia
    Posts
    45

    Question How to solve warnings that appear when building my DLL...

    Hi,

    As it may be apparent from my previous thread, I am trying to get 'making my own DLLs' sorted out. I ran into a problem when I was building my DLL yesterday (which just contains a few classes). Some of my classes have members that are of the type 'std::string', and while the DLL builds without errors, numerous warnings appear. These are all of the following form:
    Code:
    c:\Program Files\Webots\include\controller\mycpp\webots\Device.hpp(34) :
    warning C4251: 'webots::Device::name' : class 'std::basic_string<_Elem,_Traits,_Ax>' needs
    to have dll-interface to be used by clients of class 'webots::Device'
    I understand why these warnings are occurring, as a client program is not guaranteed to have included <string>, which defines the basic_string class, and so is not guaranteed to be able to use the 'name' member of the Device class for example, in the case above. I do not know however, how to get rid of these warnings, without simply ignoring or disabling them. There has got to be a way around this...

    And just for the record, I use MSVC++ 2003.

    Thanks,

    Philipp
    I program solely as a hobby so this is definitely not homework.
    Best thing that's been said to me:
    I was so pleasantly surprised to see another post in this thread, and yours was brilliant; a fitting end to a subject (matrix manipulations of all kinds) that is quite intriguing.
    Read this thread to find out why...
    Cannibalism

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    You shouldn't pass CRT or STL objects across module (dll/exe) boundaries. When you export a class, you implicitly export all members and base classes.

    http://msdn.microsoft.com/en-us/library/ms235460.aspx
    http://msdn.microsoft.com/en-us/library/twa2aw10.aspx

    Any easy solution is to use the pimpl idiom to "hide" implementation details.
    http://www.gotw.ca/gotw/024.htm

    gg

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Actually you can pass STL objects it's just that to do so requires a specific export statement. I believe the docs you referred to explain this.

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Yes, but it's not safe unless you use the exact same STL implementation with the exact same build options. It's just too easy for things to go wrong.

    gg

  5. #5
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by Codeplug View Post
    Yes, but it's not safe unless you use the exact same STL implementation with the exact same build options. It's just too easy for things to go wrong.
    I agree.
    There's a reason Microsoft never do it.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  6. #6
    Registered User starcatcher's Avatar
    Join Date
    Feb 2008
    Location
    Australia
    Posts
    45

    Question How to do that?

    I read through all the links you gave me, but I still don't understand how to use the pimpl_ idiom in a way that would help me with my problem. Could you help me by describing how I could use it for example with this class, which appears in one of my headers:
    Code:
    #include <webots\MyCpp.hpp>
    #include <string>
    
    namespace webots {
      class DECLSPEC Device {
        public:
          virtual ~Device() {}
          const std::string getName() const {
            return name;
          }
          bool isValid(void) const {
            return (tag!=0);
          }
        protected:
          Device(const std::string &name);
          WbDeviceTag getTag() const {
            return tag;
          }
        private:
          WbDeviceTag tag;
          std::string name;
      };
    }
    The definition of DECLSPEC is as follows, which is taken from MyCpp.hpp:
    Code:
    // Define DLL macros
    #ifdef MYCPPCONTROLLER_EXPORTS
    #define DECLSPEC	__declspec(dllexport)
    #else
    #define DECLSPEC	__declspec(dllimport)
    #endif
    Or is there another way that I could overcome the warnings?

    Thanks,

    Philipp
    Last edited by starcatcher; 12-14-2008 at 08:28 AM. Reason: Added question at end
    I program solely as a hobby so this is definitely not homework.
    Best thing that's been said to me:
    I was so pleasantly surprised to see another post in this thread, and yours was brilliant; a fitting end to a subject (matrix manipulations of all kinds) that is quite intriguing.
    Read this thread to find out why...
    Cannibalism

  7. #7
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Ideally, your DLL interface would only expose / transfer POD types - or other exported types. Since Device is using std:string, it's implicitly exported (which causes the warning). Here is how you could either change to POD's only, or use PIMPL idiom to hide the implementation details within the DLL - separate from the DLL interface.
    Code:
    class foo
    {
        std::string m_name;
    
    public:
        foo(const std::string &name) : m_name(name) {}
        ~foo() {}
    
        std::string GetName() const {return m_name;}
    };//foo
    
    class foo_POD
    {
        char *m_name;
    
    public:
        foo_POD(const char * name) : m_name(strdup(name)) {}
        ~foo_POD() {free(m_name);}
    
        const char* GetName() const {return m_name;}
    };//foo_POD
    
    class foo_pimpl
    {
        struct foo_imp; // forward declaration
        foo_imp *m_pimpl;
    
    public:
        foo_pimpl(const char *name);
        ~foo_pimpl();
    
        const char* GetName() const;
    };//foo_pimpl
    
    // ----------------- foo_pimpl.cpp --------------------
    
    struct foo_pimpl::foo_imp
    {
        std::string m_name;
    };//foo_imp
    
    foo_pimpl::foo_pimpl(const char *name)
    {
        m_pimpl = new foo_imp;
        m_pimpl->m_name = name;
    }//constructor
    
    foo_pimpl::~foo_pimpl()
    {
        delete m_pimpl;
    }//destructor
    
    const char* foo_pimpl::GetName() const
    {
        return m_pimpl->m_name.c_str();
    }//GetName
    If you are the only customer of your DLL - and can build all modules that use it when ever it changes (with identical project settings) - then you could keep what you have and explicitly export std::string to get rid of the warning. Another link to read: http://support.microsoft.com/default...B;EN-US;168958

    gg

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. non-MFC DLL with MFC app question.
    By Kempelen in forum Windows Programming
    Replies: 10
    Last Post: 08-20-2008, 07:11 AM
  2. building a DLL
    By sass in forum C++ Programming
    Replies: 1
    Last Post: 03-02-2006, 05:25 AM
  3. dll communicating between each other
    By cloudy in forum C++ Programming
    Replies: 5
    Last Post: 06-17-2005, 02:20 AM
  4. DLL and std::string woes!
    By Magos in forum C++ Programming
    Replies: 7
    Last Post: 09-08-2004, 12:34 PM
  5. .lib vs .h vs .dll
    By Shadow12345 in forum C++ Programming
    Replies: 13
    Last Post: 01-01-2003, 05:29 AM

Tags for this Thread