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?
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
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;
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.
Related
For example you have such situation:
1)Header file with some class definition that contain some member function (def.h).
2)That header is included into .cpp files with the same name that resides in a separate folders.
3)That .cpp files impements same function from def.h but in different way.
3)Then we include that header into some main.cpp and call function with multiple impementation and compile that whole project.
Question: will it compile without errors? What function implementation will be chosen?
Defining a function in two separate places violates One Definition Rule.
One and only one definition of every non-inline function or variable that is odr-used (see below) is required to appear in the entire program (including any standard and user-defined libraries). The compiler is not required to diagnose this violation, but the behavior of the program that violates it is undefined.
To have well-defined behavior, you should either:
Link just one of the definitions in the final program
Use overloads instead
Use polymorphism/inheritance instead
I'm trying to use a third party C++ library that isn't using namespaces and is causing symbol conflicts. The conflicting symbols are for classes my code isn't utilizing, so I was considering creating custom header files for the third party library where the class declarations only include the public members my code is using, leaving out any members that use the conflicting classes. Basically creating an interface.
I have three questions:
If the compilation to .obj files works, will this technique still cause symbol conflicts when I get to linking?
If that isn't a problem, will the varying class declarations cause problems when linking? For example, does the linker verify that the declaration of a class used by each .obj file has the same number of members?
If neither of those are a problem and I'm able to link the .obj files, will it cause problems when invoking methods? I don't know exactly how C++ works under the hood, but if it uses indexes to point to class methods, and those indexes were different from one .obj file to another, I'm guessing this approach would blow up at runtime.
In theory, you need identical declarations for this to work.
In practice, you will definitely need to make sure your declarations contain:
All the methods you use
All the virtual methods, used or not.
All the data members
You need all these in the right order of declaration too.
You might get away with faking the data members, but would need to make sure you put in stubs that had the same size.
If you do not do all this, you will not get the same object layout and even if a link works it will fail badly and quickly at run-time.
If you do this, it still seems risky to me and as a worst case may appear to work but have odd run time failures.
"if it uses indexes ": To some extent exactly how virtual functions work is implementation defined, but typically it does use an index into a virtual function table.
What you might be able to do is to:
Take the original headers
Keep the full declarations for the classes you use
Stub out the classes and declarations you do not use but are referenced by the ones you do.
Remove all the types not referenced at all.
For explanatory purposes a simplified explaination follows.
c++ allows you to use functions you declare. what you do is putting multiple definitions to a single declaration across multiple translation units. if you expose the class declaration in a header file your compiler sees this in each translation unit, that includes the header file.
Therefore your own class functions have to be defined exactly as they have been declared (same function names same arguments).
if the function is not called you are allowed not to define it, because the compiler doesn't know whether it might be defined in another translation unit.
Compilation causes label creation for each defined function(symbol) in the object code. On the other hand a unresolved label is created for each symbol that is referenced to (a call site, a variable use).
So if you follow this rules you should get to the point where your code compiles but fails to link. The linker is the tool that maps defined symbols from each translation-unit to symbol references.
If the object files that are linked together have multiple definitions to the same functions the linker is unable to create an exact match and therefore fails to link.
In practice you most likely want to provide a library and enjoy using your own classes without bothering what your user might define. In spite of the programmer taking extra care to put things into a namespace two users might still choose the same name for a namespace. This will lead to link failures, because the compiler exposed the symbols and is supposed to link them.
gcc has added an attribute to explicitly mark symbols, that should not be exposed to the linker. (called attribute hidden (see this SO question))
This makes it possible to have multiple definitions of a class with the same name.
In order for this to work across compilation units, you have to make sure class declarations are not exposed in an interface header as it could cause multiple unmatching declarations.
I recommend using a wrapper to encapsulate the third party library.
Wrapper.h
#ifndef WRAPPER_H_
#define WRAPPER_H_
#include <memory>
class third_party;
class Wrapper
{
public:
void wrappedFunction();
Wrapper();
private:
// A better choice would be a unique_ptr but g++ and clang++ failed to
// compile due to "incomplete type" which is the whole point
std::shared_ptr<third_party> wrapped;
};
#endif
Wrapper.cpp
#include "Wrapper.h"
#include <third_party.h>
void Wrapper::wrappedFunction()
{
wrapped->command();
}
Wrapper::Wrapper():wrapped{std::make_shared<third_party>()}
{
}
The reason why a unique_ptr doesn't work is explained here: std::unique_ptr with an incomplete type won't compile
You can move the entire library into a namespace by using a clever trick to do with imports. All the import directive does is copy the relevant code into the current "translation unit" (a fancy name for the current code). You can take advantage of this as so
I've borrowed heavily from another answer by user JohnB which was later deleted by him.
// my_thirdparty.h
namespace ThirdParty {
#include "thirdparty.h"
//... Include all the headers here that you need to use for thirdparty.
}
// my_thirdparty.cpp / .cc
namespace ThirdParty {
#include "thirdparty.cpp"
//... Put all .cpp files in here that are currently in your project
}
Finally, remove all the .cpp files in the third party library from your project. Only compile my_thirdparty.cpp.
Warning: If you include many library files from the single my_thirdparty.cpp this might introduce compiler issues due to interaction between the individual .cpp files. Things such as include namespace or bad define / include directives can cause this. Either resolve or create multiple my_thirdparty.cpp files, splitting the library between them.
As far as I know it's impossible to have a function declared as "inline" in a lib file and have that function "magically inlined" into a caller function into another project (since linking is not the same as compiling and the latter happens before).
How could I inline a function when having multiple functions (into multiple libraries) that have the same declaration but different definition?
e.g.
obj1.lib
void function1() { printf("Hi"); }
obj2.lib
void function1() {printf("whatsup?"); }
main.cpp
void function1();
int main()
{
function1(); // I'd like to be able to inline this, I can steer the linking against obj1 or obj2, but I can't inline this one
}
To inline a function from an object (or a library) file you'll need this object file be compiled with link-time optimization (LTO). See Inlining functions from object files for more details.
Even if you inline functions, they always have to have the same definition: having different defintions for the same entity in a C++ program is a violation of the one definition rule (ODR) specified in 3.2 [basic.def.odr]. ODR violations are often not detected by compilers and linkers and tend to result in rather weird problems.
You'll need to make sure the functions are different, e.g., using one of these techniques:
Give them a different name.
Put the functions into a namespace.
Give the functions a different signature.
Make the static to have them visible only in the given translation units.
The simplest you can do is to give the functions different names.
If you want built-time selection of a function with a given name, that has 2 or more different implementations, and you want to support machine code inlining of that function, then declare it as inline, which requires also supplying the implementation in each variant's header, and use include and lib paths to select the relevant header (for compilation) and lib (for linking) – they'd better match. As with any inline function this doesn't guarantee machine code inlining. With respect to machine code inlining inline is just a hint (it's guaranteed effect is about permitting a definition in each translation unit, and requiring such a definition in each translation unit where it's used).
How to use include and lib paths depends on your toolchain.
Edited in response to Sam Cristall's comment.
If you mean "inline at compile time" then:
In order to use a library you need to include the header file(s) associated with that library. If the desired function is declared inline in that header and the function definition (the body of the function) is available, then the compiler will (at it's discretion) inline the function. Otherwise it won't.
If you mean "inline at link time" (an unfortunate overloading of the word "inline") than see the other answers
I already know that, when I put the definition of a member function into a header and mark the function as inline, the code in the function gets inlined into any place where the function is called out of a .cpp file, so when it comes to a compiled binary, I know where the function's code is located -- within the compiled code of any .cpp file that depends on it. But what happens if I don't mark a function in a header with inline and the function's body is large enough to make the compiler choose not to inline it? In the context of a static/dynamic library the function's class belongs to, where does the function's code is compiled to? Or is it not compiled at all and the final destination for the function's code is a compiled .cpp of a client of the library? If it's the latter case, does the function's code still gets inlined even if I didn't mark it with inline (because its code was too "heavy")? And finally, is MSVC compiler's behavior in this case differs from the GCC's one?
And sure, I realize that putting member functions I want to be inlined into .h file (or .inl file) and "heavy" function into .cpp file would make things crystal clear, but I would really like to avoid breaking a class' implementation across files, hence is the interest.
When you mark a function inline you're not forcing the compiler to inline it at every place it's called, you're just telling it that that the definition is inline and it should expect duplicate copies in different compilation units. The actual code will be compiled at least once for every compilation unit where you include the header and call the function.
If you don't declare it inline, the linker should complain about multiple definitions of the function, even if those definitions are identical.
It's compiled directly into each translation unit that includes your header. If there is more than one such file you violate the one definition rule and make your program malformed.
If you really want to put all your code in one file, put it in the header and mark the function inline. It's only a suggestion so if the function is too big, the compiler won't inline it anyway, it will be compiled exactly like a non-inline function. But note that this is not canonical C++ because it can drastically increase compilation times. The normal pattern is in fact to separate the interface (headers) from the implementation (source file(s)). If the compiler decides to not inline the function, it will be written into the compiled object file for each translation unit that includes the header, and the linker will be required to pick an instance from one of the object files, throwing away the rest (since the code for each version is identical).
As you know, "inline" is merely a "request" to the compiler - nothing more.
Moreover, there's nothing preventing you from declaring a standalone "static" function in a header. At which point the SAME binary code gets DUPLICATED in every object file whose source file #include's the header.
Guess what - the same thing can happen with inline functions :)
Personally, I like to see nothing but class and struct definitions, typedefs, constants, function prototypes ... and externs ... in a header file.
Is there any difference between inline member function (function body inline) and other normal member function (function body in a separate .cpp file)?
for example,
class A
{
void member(){}
};
and
// Header file (.hpp)
class B
{
void member();
};
// Implementation file (.cpp)
void B::member(){}
There is absolutely no difference.
The only difference between the two is that the member inside the class is implicitly tagged as inline. But this has no real meaning.
See: inline and good practices
The documentation says that the inline tag is a hint to the compiler (by the developer) that a method should be inlined. All modern compilers ignore this hint and use there own internal heuristic to determine when a method should be inlined (As humans are notoriously bad and making this decision).
The other use of inline is that it tells the linker that it may expect to see multiple definitions of a method. When the function definition is in the header file each compilation unit that gets the header file will have a definition of the function (assuming it is not inlined). Normally this would cause the linker to generate errors. With the inline tag the compiler understands why there are multiple definitions and will remove all but one from the application.
Note on inlining the processes: A method does not need to be in the header file to inlined. Modern compilers have a processes a full application optimization where all functions can be considered for inlining even if they have been compiled in different compilation units. Since the inline flag is generally ignored it make no difference if you put the method in the header or the source file.
Ignore the word inline here and compiler hints because it is not relevant.
The big practical difference in A and B is when they are used in different libraries.
With the case of A you can #include the header and are not required to link against anything. So you can use this class from different applications / libraries without any special linkage.
With the case of B, you need B.cpp and this should be compiled only into one library / application. Any other library or application that needs to use this class will need to link against the one that contains the actual body of the code.
With some setups / implementations you will need to specifically mark the class as "exported" or "imported" between libraries (for example with Windows you can use dllimport / dllexport and with GNU you can use attribute(visibility="default") )
The first one is implicitly inline, i.e. suggesting the compiler to expand it at the call site.
Other than the inline thing, there's a difference in that you could put more definitions in between the definition of class B, and the definition of the function.
For example, B.cpp might include header files that B.hpp doesn't, which can make a significant difference to the build process for large projects.
But even without a separate translation unit, you can occasionally have a circular dependency that's resolved by separating the definitions. For example the function might take a parameter of a type that's forward-declared before B is defined, then defined by the time the function is defined. If that type uses the definition of B in its own definition, it can't just be be defined before B.