digint/tinyfsm

Unresolved external symbol tinyfsm::Fsm<...>::current_state

ezemskov opened this issue · 7 comments

Hi Axel,
I'm trying to use tinyfsm in a Windows DLL, i.e. my concrete FSM is defined in DLL and referenced in an (unit test) executable that links this DLL's import library :

in DLL sources :
class __declspec (dllexport) AutopilotFSM : public tinyfsm::Fsm<AutopilotFSM> {...}

in executable sources :
class __declspec (dllimport) AutopilotFSM : public tinyfsm::Fsm<AutopilotFSM> {...}

It builds and runs OK, until I try to dispatch an event from the executable :
AutopilotFSMList::template dispatch<EventType>(event);

When I try to link the executable, I get a linker error below.
I've double-checked the DLL (with dependency walker), and current_state IS defined there.

error LNK2001: unresolved external symbol "private: static class AP::AutopilotFSM * tinyfsm::Fsm::current_state" (?current_state@?$Fsm@VAutopilotFSM@AP@@@tinyfsm@@0PAVAutopilotFSM@AP@@A)

Would you have any suggestions ?
Thanks,
Eugene

Maybe the problem is that Fsm<>::current_state is defined in the header, which is fine as the linker eliminates duplicates according to the standard. In the case of a DLL this might be a problem.

Have you tried to move the definition to a compilation unit used only for the DLL? In other words, remove lines 210, 211 from your cpp-files linked to the DLL:

#ifndef LINKING_TO_DLL
  template<typename F>
  typename Fsm<F>::state_ptr_t Fsm<F>::current_state;
#endif

Refs:
https://stackoverflow.com/questions/7848865/dll-exporting-static-members-of-template-base-class

Edit: for the record: what compiler are you using?

Thanks Axel,

tried to conditionally restrict the definition to DLL only, didn't work (the same definition is linked into the DLL and not resolved by the linker).
Compiler is Visual Studio 2013 (vc12).
Thanks for pointing me along these lines, anyway - will investigate further on ocassion (or maybe it wouldn't arise on Linux/gcc, my target platform).

@ezemskov could you please try the current master branch and tell me if the problem persists? I have done some adaptions in the way TinyFSM sets the initial state, and would be interested if it makes any difference with your compiler suite.

Tried master - doesn't compile (even mealy_machine.cpp example) on vc12.
Apparently you're using much more C++14 features now :)

Yes, I'm using "variable templates" now (commit 2e44315), which simplifies things but is a C++14 feature.

That's one point why I thought it might work for you now (thinking that everyone should have C++14 capable compiler by now).

Anyways, thanks for testing!

C++ compilers for embedded development usually fall behind by about 5 years. I have used the current master and reverted the state_instance change and it works for me on a rusty but not easily replaceable g++ 4.9.

Good point. The benefits of "variable templates" are too small (basically only code readability) to justify C++14 dependency.

Switched back to C++11 in: dde1d49