I have static library (.lib) in VS2010 and am linking it to my test project.
The lib has a factory that I create using the below MACRO:
#define REGISTER_FACTORY(mType, my_class) \
class Factory##my_class : public CAbstractFactory\
{\
public:\
Factory##my_class() : CAbstractFactory(mType){}\
CBaseClass *Create()\
{ return new my_class(); }\
};\
static Factory##my_class StaticFactory##my_class;
What is supposed to happen is that in the CAbstractFactory the new factory gets registered by mtype
. But when I check the factory the factory does not exist.
It works fine when I use a DLL instead of a .lib. My guess is that the linker does not include the static variable as it is not referenced or the static variable was not even included in the library.
How can I force the linker to include all objects from the static library in my .exe.
I use the macro like this:
// Register factory that can create CMyObject with ID=100
REGISTER_FACTORY(100, CMyObject);
class CMyObject
{
};
The CAbstractFactory looks like this:
class CAbstractFactory {
CAbstractFactory(int id) {
CFactory::instance().add(id, this);
}
}
Then some where else in the code, my main .exe I use:
CBaseClass *pObject = CFactory::instance().Create(100);
This will then give my a new CMyObject
. The idea is that I have many different kind object and I have a database containing the id specifying the kind of objects I need.
100
is just an example.
So indeed, I do not reference anything from the .lib directly but I want to be able to create the objects using my factory
The CFactory class is a simple class that keeps a register (in a map) of all the CAbstractFactory classes and delegates the create method to the correct factory.
CFactory &CFactory::Instance()
{
static CFactory instance;
return instance;
}
The main problem lies in the fact that I do not reference anything from the .lib as it is all done through the CFactory. It works if I make it a DLL and make sure I add some reference to this DLL to make sure it is loaded. But for a .lib, I even added a dummy function to make sure I have at least one reference that doesn't include the rest of the code.
In C, static variables can only be initialized using constant literals.
A static variable in a block is initialized only one time, prior to program execution, whereas an auto variable that has an initializer is initialized every time it comes into existence. A static object of class type will use the default constructor if you do not initialize it.
3) Static variables (like global variables) are initialized as 0 if not initialized explicitly.
Global and static variables are initialized to their default values because it is in the C or C++ standards and it is free to assign a value by zero at compile time. Both static and global variable behave same to the generated object code.
I had a similar problem and solved it by setting the lib project as a dependency of the main app project and then setting 'Link Library Dependencies' and 'Use Library Dependency Inputs' to Yes for the main project.
Update:
Recently I discovered that Visual Studio 2015 now supports a /WHOLEARCHIVE
linker flag. I can't find it through the linker options, but you can add it as an additional command line option. It works similar to the GCC flag -whole-archive
and you add it to your target linker flags (not to the static lib flags).
For example, specify /WHOLEARCHIVE:lib_name
as an additional linker command line option and it will include all symbols from that lib. You can do this more than one lib as well.
If you use this /WHOLEARCHIVE:lib_name
you no longer need the 'Link Library Dependencies' and 'Use Library Dependency Inputs' set to Yes. This is perfect for solutions generated through CMAKE. See a related answer here: https://stackoverflow.com/a/42083877/1151329
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With