0

I am trying to use factory mode to create some derived class.

Here are the details about it:


Purpose:

There are two classes DerivedA and DerivedB derived from BaseClass. Class DerivedA is defined in derived_class_A.h/cpp and DerivedB in derived_class_B.h/cpp.

Also there is a factory class Factory in factory.h/cpp to create DerivedA or DeriveB.

Our purpose is that, the Factory is allow to create DerivedA if and only if derived_class_A.cpp is compiled, meanwhile we don't want to have any information about DerivedA in the factory.h/cpp.

So we cannot use switch case(){...} to call new DerivedA() in the factory, nor can we use MACROS to distinguish DerivedA and DerivedB.


Our Implementation

In the Factory class, we have a static method:

template<class classname> Factory::RegisterClass<classname>(int key);

It uses a std::map to map the key keyA to the new DerivedA() function, and keyB to new DerivedB() function.

Then in the BaseClass* Factory::CreateClass(int Key) method, it can get the creator of DerivedA/DerivedB according to the key.

In derived_class_A.cpp, we are trying to calling the RegisterClass during the library loading. Here is the way we use:

class tempClassA { tempA() { Factory::RegisterClass<DerivedA>(keyA); } };
static tempClassA tempA;

In this way, if derived_class_A.cpp exists, the RegisterClass of DerivedA will be called when the static variable tempA is initialized.

If derived_class_A.cpp is not compiled, then static variable tempA doesn't exist and the RegisterClass of DerivedA won't be called. This is the result we expected.


Issues:

This method works perfectly when we build the code as a shared library directly, or as an executable.

However, when we build it to a static library and then linked into a final shared library with other libs, seems that the derived_class_A.o is not linked into the shared library.

We think it is caused by the fact that no definitions in derived_class_A.cpp is referred explicitly in other files. The Factory class call the creator of DerivedA implicitly.

Here is an experiment to prove that it is not linked:

  1. We declare a function using "extern", but doesn't implement it. We call this fake function in derived_class_A.cpp, and it doesn't report any linking error either in the static library building or latter building the static lib into the final shared library.
  2. If we define a variable "int A" in derived_class_A.cpp and refer it using "extern int A" in factory.cpp. (In fact we can't do that in our project since we can't including any information from derived_class_A.cpp in factory.cpp.) In this case derived_class_A.o will be linked as it will report an linking error about the fake function we added in step 1.

Questions

  • So can I force a file to be linked in the final library even non of its definition is referred external?
  • If not, is there any other choice to implement this mechanism? I know on Linux __attribute__((constructor)) can guarantee the registerClass function called when the library is loaded. But I didn't find any similar tools on Windows VS.

Thanks a lot for watching this.


AleXelton
  • 767
  • 5
  • 27
Fan
  • 1
  • Looks suspiciously like https://stackoverflow.com/questions/3867254/what-is-the-microsoft-visual-studio-equivalent-to-gcc-ld-option-whole-archive – MSalters Aug 04 '17 at 07:24
  • Hi MSalters, thanks a lot. That's exactly the issue I met with, and using the /WHOLEARCHIVE can solve it completely. – Fan Aug 07 '17 at 01:21

0 Answers0