C++ static variable in .lib does not initialize - c++

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.

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

static defines an object with internal linkage --> if it's not used internally in the same translation unit, it can be optimized out. Remove the static from your instantiation for the object to have external linkage - Factory##my_class StaticFactory##my_class;

Related

How to force include static objects from a static library in C++ (MSVC 11)

I am trying to initialize a static object in a C++ file which is trying to auto register a class to a factory in its constructor (like any standard auto-registration problem). The problem is, this is compiled to a static library, and while linking to an executable, that is optimized away. There should have been a very simple solution to that, but surprisingly, looks like it's not that simple.
Here's my class:
In Factory.h (part of static lib project)
class DummyClass : public BaseFactoryClass
{
int mDummyInt;
public:
DummyClass()
{
std::cout << "Pretending to register myself to the factory here\n";
}
};
In some cpp, let's say Circle.cpp (still part of the static lib project)
static DummyClass dum;
main.cpp (part of the executable)
//some code accessing the BaseFactoryClass of the Registered derived classes.
Now, since the static object is not 'directly' used in the executable project, it's skipped from the linked library.
I want to make it work in MS VC11 (Visual Studio 2012) (and GCC 4.8.*, but that's for later). Looking at other questions, I tried various things so far, which don't seem to work:
Looks like /WHOLEARCHIVE linker option is only supported from Visual
Studio 2015 (We're using VS 2012)
Specifying /OPT:NOREF should have worked (I tried several combination of this with other flags like /OPT:NOICF), but it doesn't work for anyone.
I tried #pragma comment (linker, "/include:symbolName") in the header file, but that gives a linker error about symbol being unrecognized. (And also that wouldn't work in GCC, but probably --whole-archive works there).
There is a flag in Visual Studio Linker Settings that allows linking all object files individually rather than the static lib, but I don't want to go that route. Also, preferably I'd just want to write something in the source (.cpp) of each individual class I want to automatically register, with all the boiler plate code and macros being in a central header like BaseFactory.h etc. Is there any way to do it (even in C++ 11 where there's a guarantee that a symbol will be initialized)? Want to make the registration of a new class as easy as possible for any new developer.
In MSVC you have a linker pragma you can use for that purpose:
#pragma comment (linker, "/export:_dum")
This way whenever the linker is run, it will force link _dum in your executable or DLL.
A better way, though, would be to consider using a DLL instead of a static library. Then you avoid this problem altogether since on each load of the DLL that static variable will be initialized.

utilizing a static library to create an import library

I am interested in using my static lib to create a dll (implicitly linking). which means I need to (in vs2008)
create a dll project that should generate the following:
header file (which have export function declarations. These are simple wrappers to actual functions in the static lib using __declspec(dllexport) which are in the .cpp )
import lib which will be made as a result of creating the dll
the actual dll which is created.
I have made a test program that will utilize the above dll(including the import lib/header files) to test it.
in this I have included all the three items. now the exe compiles/links without issue.
however in the main.cpp when i call the exported functions (with the associated __declspec(dllimport) call it never seems to execute. I am uncertain why this is?
Its almost like the even though the exe can see the exported function in in the dll...the dll cannot call on the code that is in the static lib?
i just cannot answer why my exe can't see the code in the static lib? do i need an archiver/librarian for vs2008 to include all those obj files as part of the import lib?
I am at a loss and am not sure how to test this?
other than just making my static lib directly into a dll. I wanted to try this method. I know i am missing something...i have read all over the place and i am just stuck. There were some threads here that had some people posting something similar but i can't seem to get it. please be as detailed as possible as I am new to this. thanks again.
update 1:
ok so currently i added the extern line to the function prototype and now it sees the exported function from the dll. however, now the only issue left is that:
i can't invoke the function that this exported function (aka wrapper) is trying to call. which happens to be in the static library. how should my exe get visibility to that static library function. I know it can be done because I think there was one other person on this board who was able to make this work.
update 2: my setup is exactly like this questioner...
How to force inclusion of an object file in a static library when linking into executable?
but i am not using explicit linking. i am using implicit linking. my real issue is how to call a static lib function in my dll wrapper which is exported to the exe?
If the app and DLLs are MFC app/dlls, then make sure that the application and all dlls are either "Debug" versions or "release" versions and not a mix.

Not all symbols of an DLL-exported class is exported (VS9)

I'm building a DLL from a group of static libraries and I'm having a problem where only parts of classes are exported.
What I'm doing is declaring all symbols I want to export with a preprocessor definition like:
#if defined(MYPROJ_BUILD_DLL)
//Build as a DLL
# define MY_API __declspec(dllexport)
#elif defined(MYPROJ_USE_DLL)
//Use as a DLL
# define MY_API __declspec(dllimport)
#else
//Build or use as a static lib
# define MY_API
#endif
For example:
class MY_API Foo{
...
}
I then build static library with MYPROJ_BUILD_DLL & MYPROJ_USE_DLL undefined causing a static library to be built.
In another build I create a DLL from these static libraries. So I define MYPROJ_BUILD_DLL causing all symbols I want to export to be attributed with __declspec(dllexport) (this is done by including all static library headers in the DLL-project source file).
Edit:
Note on unrefenced symbols: Linker options Keep Unreferenced Data (/OPT:NOREF) and Do Not Remove Redundant COMDATs (/OPT:NOICF) is set so that no unreferenced symbols will be removed.
Ok, so now to the problem. When I use this new DLL I get unresolved externals because not all symbols of a class is exported. For example in a class like this:
class MY_API Foo{
public:
Foo(char const* );
int bar();
private:
Foo( char const*, char const* );
};
Only Foo::Foo( char const*, char const*); and int Foo::bar(); is exported. How can that be? I can understand if the entire class was missing, due to e.g. I forgot to include the header in the DLL-build. But it's only partial missing.
Also, say if Foo::Foo( char const*) was not implemented; then the DLL build would have unresolved external errors. But the build is fine (I also double checked for declarations without implementation).
Note: The combined size of the static libraries I'm combining is in the region of 30MB, and the resulting DLL is 1.2MB.
I'm using Visual Studio 9.0 (2008) to build everything. And Depends to check for exported symbols.
Edit:
For the ones who wonder why I don't just build a DLL from each of the static libraries: I can't because they cross-reference each other (that's why I need to group them together in one a single DLL). I know, it's horrible I can't really understand the logic behind it.
Remember that when you link against a static LIB, by default the linker is only pulling in the functions, classes, and data that the client (which in this case is your DLL) actually references.
So what happens is this:
You build your static LIB, and that's fine. This LIB is 100% valid.
You now build your static DLL around the original binary LIB. It pulls in only the stuff that it actually references. It doesn't pull in the entire class definition which is what it needs to do. This DLL, though it builds, is invalid.
A client then uses the DLL, and expects to see a complete binary definition for the exported class, because that's what the client sees in the accompanying header file.
However the class has only been partially imported, and this is why you're getting those link errors.
To fix:
If you're able to, don't build your DLL off your static LIB. Build your DLL off the original source code. And build your static LIB off the original source code.
Otherwise you can possibly fiddle with linker settings but I strongly recommend option 1 above. Note that OPT:NOREF won't work here as OPT:NOREF has no effect on static LIBs.
What wont't fix it:
High-level linker tweaks like OPT:NOREF, anything involving COMDATs, etc. If you want those functions present, you have to make sure they're referenced, either by referencing them, or by telling the linker explicitly, "hey, this Symbol X is referenced".
As a side note:
Anytime I build a DLL or LIB, I build both a DLL and a LIB, using exactly the technique you're using. Having a single code base that can generate either a DLL or a LIB by toggling a setting is ideal. But building a DLL off of a (binary) static LIB when you own the source code for both... I'm having a hard time imagining when such a scenario would be necessary.
The problem is surely that you use the already-built static .lib in your DLL project. That cannot work, you have to rebuild the .lib so that the functions get the __declspec(dllexport) declarator and will be exported by the linker.
At that point, it just isn't all that useful anymore to create the DLL compatible version of the .lib in the first place. Just create two projects, one that creates the static .lib, another that creates the DLL. Technically it is possible to still use the static .lib in your DLL project but you'll have to export the functions with a .def file. That can be high maintenance if the library has a lot of exports.
This is probably years too late, but OP's complaint was that a private method (the destructor) was not exported from a dllexport'd class. Isn't that normal? No external user is allowed to call a private method.

static Member access linker problems

gph is a singleton class with no getInstance method
class gph
{
public:
static void newfun();
static void newfun1();
//...//
private:
gph();
};
This class gets build into a static library
Now I have a Dll from where I need to access the static function . So class A is a part of a Dll
I have a C++ member function say
void A:: fun()
{
gph::newfun() ; //accessing a static function : gives linker errors
}
On the other hand if I make fun() as static it doesnt give me any linker errors . But I do not want to make fun() as static
Most of what I work on deals with statically linked libraries, so this answer may not apply, but may clue you in to the problem. So based on that and what I'm looking at right now, my first thought would be to check that in the dll you're building, you've included the static library.
An unresolved symbol usually means that either the signature doesn't match or you're not including the necessary library. It varies from compiler to compiler, but most make you specify the library directory (sometimes denoted by -L in a command line) and the actual library to be linked in (sometimes denoted by -l).
Since I don't use DLL's that much, my understanding of them is similar to building an executable. If you use dynamic linking when you build, the path of the libraries you are linking to are embedded in your executable, so your executable size is smaller, but is dependent on the library path they are linked to on not moving.
So when you're building your DLL, make sure you've compiled the cpp for class gph and created a static library for it. Then when you use it in class A, you include the header and link in the library.
I think it is the calling convention issue.
Please try the following code:
class gph
{
public:
static void __cdecl newfun();
//...//
};

Why to use __declspec(dllexport)? Seems to be working without it

Been a while since I have programmed in C++, so the whole export/import idea slipped off my mind.
Can you explain me why to use __declspec(dllexport) & import thingy if it looks like I can use classes from other libraries without those.
I have created a solution in VC++ 2005, added the console applicaiton project and two dll libraries projects. Then create ClassA in a LibA, ClassB in LibB project.
Once I have included ClassA.h & ClassB.h into my console app source code, and has linked it with a LibA.lib and LibB.lib I was able to create and use instances of ClassA and ClassB in a console applicaiton. So basically I was able to use classes without exporting/importing them using __declspec.
Can you explain me - what I am missing here.
Once I have included ClassA.h & ClassB.h into my console app source code, and has linked it with a LibA.lib and LibB.lib I was able to create and use instances of ClassA and ClassB in a console applicaiton.
This sounds like you have used static linking. This works without the __declspec(dllexport) in the same way as linking with the object files of your classes directly.
If you want to use dynamic (run-time) linking with a DLL, you have to use either the mentioned declaration or a DEF-file specifying the exported functions. DLLs contain an exports table listing the functions exposed to other executables. All other functions remain internal to your DLL.
Perhaps you are confused coming from the Linux world, where the situation is the other way round: All symbols are visible externally by default.
You would use __declspec(dllexport) if you wanted to provide symbols in your dll for other dlls/exes to access.
You would use __declspec(dllimport) if you wanted to access symbols in your dll/exe provided by another dll.
Not necessary if you are linking against a static .lib.
If you are including .h files and linking to .lib files then you can drop the DLL declarations. Why do you need a dynamic link library if you only need static linking?
The export declaration marks the function as available for exporting. The declaration you are using may be a macro for "extern" and "pascal" It's been years since I've done this but I think DLLs function calls have a different ordering of pushing params on the stack and the allocation of the return result is done differently (the pascal flag). The extern declaration helps the linker make the function available when you link the library.
You may have missed the step of linking the DLL - the linker will take classA.lib and turn it into classA.dll ( you may need to setup a setupA.def file to define the DLL library). Same applies to ClassB