9

I am trying to build a DLL from source-code from the Crysis Wars SDK, and have successfully done so in the past on previous versions of Visual Studio (namely 2005, 2008, and 2010). My specific problem is this:

Error   4   error LNK2019: unresolved external symbol "struct CTypeInfo const & __cdecl
TypeInfo<char>(char *)" (??$TypeInfo@D@@YAABUCTypeInfo@@PAD@Z) referenced in function 
"void __cdecl SwapEndian<char>(char *,unsigned int)" (??$SwapEndian@D@@YAXPADI@Z)   
G:\Noctis\Mods\Noctis\Code\GameCVars.obj    GameDll

I have attempted to clean the code in Visual Studio and rebuild it on the off-chance this'll work, but this has not changed anything.

Am I missing something here, or has something changed from C++03 to C++11 that means that this code is no longer compilable without reverting to an older version of C++?

I have successfully compiled this code on Visual Studio 2010 in both 64 bit and 32 bit, so it must be some issue related to migrating the project to Visual Studio 2015.

Compilation on 2012, 2013, and 2015 versions of Visual Studio reproduce this error but not 2010, so it seems that the change to trigger this problem was introduced in C++11.

What am I doing wrong?

Reading the answer to mem-fun is not a member of std, it could just be that I need to include a standard library that I didn't need to include in earlier versions of Visual Studio. If this is true, which library would I need to #include?

I have also created a GitHub repository containing only the original unmodified code provided from the SDK, for testing purposes (in the event I myself made a typo, which doesn't seem to be the case here but I've put the link here as it may be helpful).

If it matters, I'm using Visual Studio 2015 Enterprise edition on Windows 10 Professional x64.

Community
  • 1
  • 1
AStopher
  • 4,207
  • 11
  • 50
  • 75
  • Requesting the question to be re-opened. Added as much detail as I can, and included a GitHub repository containing the code that I am working on, therefore the problem can be reproduced. – AStopher Feb 29 '16 at 20:31
  • Your evidence suggests the problem was introduced by VS2012 , not C++11 per se. – M.M Feb 29 '16 at 21:31
  • @M.M Evidence suggests that it's C++11 that's causing it (as the main change between VS2010 and VS2012), since the code compiles perfectly as C++03 but not C++11 (could be wrong though). The code's there if further confirmation is required. – AStopher Feb 29 '16 at 21:33
  • VS2012 is a very long way from being C++11 compliant – M.M Feb 29 '16 at 21:34
  • @M.M Still, even a *small* change between versions could have triggered this. You could be correct that it's an issue with something other than the version of C++ used (*could even be an issue with the way Visual Studio upgrades the project*); that's something I'n unsure on. I also *could* simply install an older version of Visual Studio (I have licences for all versions since 2005) but I'd rather not use up disk space that doesn't need to be taken up. – AStopher Feb 29 '16 at 21:36
  • 2
    You could try creating a new project file; upgrading old project files sometimes does weird things – M.M Feb 29 '16 at 21:39
  • BTW the problem is that `TypeInfo(char *)` is not defined (not any problem with SwapEndian) – M.M Feb 29 '16 at 21:40
  • @M.M Cheers, that's something I didn't actually consider. I'll try that and report back. Also edited the question title. – AStopher Feb 29 '16 at 21:40
  • 1
    `TypeInfo(char*)` etc. are defined in the CryCommon project, AutoTypeInfo.cpp. The problem is that GameDll compiles fine - it finds the relevant .h files correctly, but when it gets to linking, the CryCommon dependency is not linked in properly and that results in the error. Hard to make more guesses, because your project is in a weird state (.sln references .vcprojx, but only .vcproj files are checked in; there are broken things like `#ifdef USE_`...) Make sure that CryCommon project is built and it is referenced by GameDll as a dependency (added as a library). – Yirkha Feb 29 '16 at 21:48
  • @Yirkha Looks like you're on the right track there; the dependencies seemed to have been unlinked (possibly by Visual Studio upgrading the project). Re-linked them and the same error still occurs (I'm a little rusty with C++, so bear with me if I did it incorrectly). Commit is being done, just taking a while. The `#ifdef USE_` problem is a typo on my part, but the `unordered_map`s don't affect the error given here. – AStopher Feb 29 '16 at 22:05
  • @Yirkha Just rebuilt the project (created a new project and copied the code across), and it seems that you have the correct answer (that the two dependency projects became unlinked). I'm transferring the rest of the project over now; please write an answer and I'll accept it + award the bounty if I confirm that you're correct (can't confirm that until the project is completely rebuilt, but so far the error isn't present). – AStopher Feb 29 '16 at 22:39
  • @cybermonkey Your further commits did not make it through (forgot to push?) Anyway, I managed to build the DLL. The other projects' compiled code should not be needed, only the .h files are sufficient. See the answer below. – Yirkha Feb 29 '16 at 22:49
  • Questions relying on off-site links are off-topic, for a few reasons. You should have produced and presented a [MCVE]. – Lightness Races in Orbit Dec 30 '16 at 17:39

1 Answers1

4

What does the error mean?

The error message hints towards a classic "declared but not defined" scenario.

TypeInfo<char>(char*) is declared in TypeInfo.h (through some macros) and declared in AutoTypeInfo.cpp in project CryCommon.

Usually you would just make sure the CryCommon project is built correctly and linked into your final GameDll project properly and that's it.

But it turns out here that the CryCommon project has not been built for a long time - it references many other Crytek libraries etc. So the problem must be that something now needs these TypeInfo<> definitions and previously it did not.

What is referencing the TypeInfo<> code?

In your project it's function CmdHelp() in Aurora/Code/GameCVars.cpp, precisely this line:

nRead = gEnv->pCryPak->FRead( buf, BUFSZ, f );

The implementation of the FRead() method is in CryCommon/ICryPak.h:

template<class T>
size_t FRead(T *data, size_t elems, FILE *handle, bool bSwap = true)
{
    size_t count = FReadRaw(data, sizeof(T), elems, handle);
    if (bSwap)
        SwapEndian(data, count);
    return count;
}

As you can see, if bSwap is true (the default), SwapEndian() is invoked there.

Why hasn't this manifested before?

Perhaps the compiler was indeed behaving differently.

Or, more likely, you have been always compiling the project as Release before. The whole byte-swapping functionality is enabled only on big-endian systems (and your target is most probably not one of those) or during debug - then the bytes are actually swapped twice to test the related code (see CryCommon/Endian.h).

What can be done to fix it?

You have several options now:

  • Keep compiling as release only (probably as before). Perhaps you will never be debugging the code in a debugger anyway.

  • Just comment the swap call in FRead() code out. You are using it to load a text file anyway, no point in swapping the characters around.

  • ...


FWIW, other things I had to do to make your code compile:

  • Check out the earlier commit before "Broken"
  • Load Mods\Aurora\Code\Aurora.sln
  • Remove non-existing .vcprojx projects
  • Add all 3 .vcproj files again, let them be converted to VS2015 ones
  • For GameDll project, add preprocessor definition _SILENCE_STDEXT_HASH_DEPRECATION_WARNING
  • For GameDll project, set enabled C++ exception handling /EHsc
  • Comment out the code above
Yirkha
  • 12,737
  • 5
  • 38
  • 53
  • That's exactly spot-on, thanks! Seems that Visual Studio didn't *quite* upgrade the project properly (could be fixable without editing code by installing all versions of Visual Studio 2005 through 2015 and upgrading the project in each). I'll award the bounty tomorrow (have to wait 21 hours). – AStopher Feb 29 '16 at 22:55
  • 1
    Well yeah, as M.M said above, beware of VS project upgrades, one has to always recheck everything - or better start a new project from scratch and avoid any legacy settings while at it. Anyway, I',m glad you got your stuff working! – Yirkha Feb 29 '16 at 22:59