-1

I am trying to a make plugin system which will have a header file for all plugins to include. In that header the version of the plugin system is defined in a #define like so:

PluginHeader.hpp:

#define PLUGIN_SYSTEM_VERSION "00.001"

class PluginSystem
{
public:
    string GetSystemVersion(){return PLUGIN_SYSTEM_VERSION; }
    void MyPluginDoStuff(){...}
}

I compile my plugin with this header in a dll and export it. Afterwards, i import it in the main application and i change the value of the #define in the calling application to be "00.002". If i call the method GetSystemVersion in the dll, then i am getting the new value "00.002".

Is this the expected behavior? How can i make the dll keep its defined value?

Yann
  • 180
  • 3
  • 14
  • 1
    If you didn't want to change the value of the define, why did you...change it? – Nathan Pierson Apr 23 '22 at 16:19
  • 2
    `GetSystemVersion` should be in a .cpp file of the dll, not in the header. – HolyBlackCat Apr 23 '22 at 16:20
  • 1
    The function is implicitly inline (defined within its class definition) so your program has undefined behaviour due to breaking the one-definition rule, and one potential symptom of that (as you are seeing) is different versions of the function (e.g. the DLL version or not) called in different compilation units. If you want to have the function in the DLL, define it outside the class definition, within a single source file (and place the corresponding object file into the DLL). – Peter Apr 23 '22 at 16:35
  • @Peter, thanks, this worked. If you put it as an answer i will accept it as correct. – Yann Apr 23 '22 at 19:41
  • @Yann - Yeah, okay. I'll expand a little to make it more complete, and post as an answer shortly. – Peter Apr 24 '22 at 01:48

1 Answers1

0

It is neither expected nor unexpected behaviour. Your program has undefined behaviour, so any outcome (whether it seems "right" or not) is possible.

Your member function PluginSystem::GetSystemVersion() is defined (implemented) within its class definition, so is implicitly inline.

The problem is, by having different definitions of the macro PLUGIN_SYSTEM_VERSION in different compilation units (e.g. in your DLL and in a separate source file that includes your header), you cause your program to have multiple definitions of PluginSystem::GetSystemVersion() (and, in fact, the whole class PluginSystem) in your program. If those definitions aren't exactly the same, you're breaking the one-definition rule. Which for an inlined function (and for a class) means that all definitions seen by different source files must be identical.

Breaking the one-definition rule means your program has undefined behaviour. Seeing different versions of an inline function being called in different compilation units (e.g. the DLL version called in some situations but not others) is one possible symptom of that.

If you want to have the function in the DLL, then

  1. Change the class definition so that the function is not inline within the class definition, and ensure that class definition is used consistently everywhere (both in all source files for your program, and in all source files for the DLL) - for example, by including the same header everywhere it is needed;
  2. In exactly one source file, for the DLL, include exactly ONE definition of the function outside the class definition.

Although not technically necessary, I'd encourage you to avoid using macros (other than include guards) in the header (or, even, using a macro for it at all - there are alternatives). If you must have a macro PLUGIN_SYSTEM_VERSION, define it locally to the single source file that defines PluginSystem::GetSystemVersion(). That avoids the possibility of confusing yourself (and increasing chances of getting unexpected behaviours) by having different incantations of PLUGIN_SYSTEM_VERSION (and code affected by it) in different parts of your program.

Peter
  • 35,646
  • 4
  • 32
  • 74