Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dllexport a class derived from std::runtime_error?

I have set up a library providing an exception class derived from the standard exception:

#include <stdexcept>
#include <string>

class BaseException : public std::runtime_error
{
    public:
        BaseException( std::string const & msg );
};

So far, so good. Compiles and handles quite well on Unix. Now I am prepping this for compilation into a Windows DLL:

#ifdef WIN32
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT
#endif

#include <stdexcept>
#include <string>

class MY_EXPORT BaseException : public std::runtime_error
{
    public:
        BaseException( std::string const & msg );
};

However, this gives me warning C4275: non – DLL-interface class 'std::runtime_error' used as base for DLL-interface class 'BaseException'.

And unfortunately, I am somewhat allergic to Microsoft-style documentation: Excessively wordy, and not very to the point. It keeps leaving me utterly confused as to what is actually expected of me to solve my problem.

Can any of you enlighten me? I could just drop the base class, but then catching std::runtime_error or std::exception would not catch my custom exception class, and I would very much prefer this to be possible. So...?

like image 455
DevSolar Avatar asked Jul 01 '14 13:07

DevSolar


1 Answers

There are a few options for you in this type of situation.

  1. Export it.
  2. Ignore it.
  3. In-line it.

It is important to bear in mind that the "correct" way to export class from a dll is to export the entire class, including bases and members. For this reason there are several techniques such as this one on CodeProject, that use an "interface" and appropriate factory to create the class (and matching destruction).

This is not too useful for you in this situation, trying to export std::runtime_error is probably more effort and likely to introduce even bigger issues later on.

Taken from the Microsoft Connect site here (webarchive), the family of these errors are essentially noise;

I recommend avoiding this in the first place - putting STL types in your DLL's interface forces you to play by the STL's rules (specifically, you can't mix different major versions of VC, and your IDL settings must match). However, there is a workaround. C4251 is essentially noise and can be silenced...

Stephan T. Lavavej (one of the maintainer's of Micrsoft's C++ library).

So long as the compiler options are consistent through the project, just silencing this warning should be just fine.

The final option is to define the BaseException class inline and not export it at all.

In my experience, the inline option landed up almost always being the easiest for exception classes.


Changes in the C++ runtime for VS2015, have resulted in changes to the exporting of std::exception (It is not exported from the runtime).

The inline option now seems to be the most appropriate at this time (your mileage may vary).

class Exception : exception {
public:
    char const* what() const override;
};

inline char const* Exception::what() const {
    /*...*/
};
like image 160
Niall Avatar answered Sep 21 '22 11:09

Niall