Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'TypeInfo<char>(char *)' isn't defined but worked pre-C++11; what changed, and how can I fix the error?

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.

like image 342
AStopher Avatar asked Jul 04 '14 20:07

AStopher


1 Answers

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
like image 159
Yirkha Avatar answered Oct 16 '22 03:10

Yirkha