Why "unresolved external symbol" in VS2010 (lnk2001) when symbol is defined in .lib? C++, boost, cpputest

484 views Asked by At

I'm getting this error from the linker:

1>PACBalancesTest.obj : error LNK2001: unresolved external symbol "public: bool __thiscall PAC::BalChgKeyComparator::operator()(class PAC::BalChgKey const &,class PAC::BalChgKey const &)const " (??RBalChgKeyComparator@PAC@@QBE_NABVBalChgKey@1@0@Z)

I must be missing something really obvious, because I've looked at the definition of the "missing" symbol repeatedly and can't see any problem.

The symbol's definition is in a .lib file. I see the following in the output from dumpbin /symbols on that .lib file:

2F0 00000000 SECTFD notype ()    External     | ??RBalChgKeyComparator@PAC@@QBE_NABVBalChgKey@1@0@Z (public: bool __thiscall PAC::BalChgKeyComparator::operator()(class PAC::BalChgKey const &,class PAC::BalChgKey const &)const )

And there are other symbols being resolved successfully from that .lib file! (In fact, from the same .obj.) [Update: I no longer think the preceding statement is true. This may be my first attempt to access any function not defined in a .h file.]

WHAT FOLLOWS IS NOT RELEVANT TO THE PROBLEM -- SO PLEASE DON'T SPEND TIME STUDYING IT!

Here's the declaration of the function (in PACBalances.h):

namespace PAC {
    class BalChgKey {
    public:
        ...
    };

    struct BalChgKeyComparator {
        bool operator()(const BalChgKey& lhs, const BalChgKey& rhs) const;
    };

    typedef std::multimap<BalChgKey, long, BalChgKeyComparator> BalChgKeyLongMMap;
};

Note that I've tried changing 'struct' above to 'class', with no effect.

Here is the calling code (in a cpputest test file):

#include "CppUTest/TestHarness.h"

#include <utility>
#include <map>
#include "PACBalances.h"

using namespace PAC;

...

TEST_GROUP(PACBalanceCUMap)
{
    BalChgKeyLongMMap empty;
    BalChgKeyLongMMap onesy;

    void setup()
    {
        // **Adding the following line caused this error to start to occur.**
        onesy.insert(std::pair<BalChgKey, long>(BalChgKey(BOPCAT_FEE, PAYMTYPE_OVERDRAFT_FEE, 4321, 41100, 1, 17), 17));
    }
    void breakdown()
    {
    }
};

And here is the definition of the operator function itself:

bool PAC::BalChgKeyComparator::operator()(
    const BalChgKey& thing1, 
    const BalChgKey& thing2
    ) const
{
    if (thing1.m_balKey.m_balCat < thing2.m_balKey.m_balCat)        return true;
    else if (thing1.m_balKey.m_balCat > thing2.m_balKey.m_balCat)   return false;
    // Fall thru if balCats are equal
    ...
    return false;
}

Please note that:

  1. The comparator, and the typedef'd multimap, works beautifully in lots of code (not shown above).
  2. The test file calls lots of other functions declared and defined in that .h file, but this is the first time I've tried calling a function defined in a separate .cpp file.
  3. My question is not why does the 'onesy.insert' call requires the comparator function. I understand that. It just happens to be the first multimap operation that I've coded in the test set that actually uses the comparator.

I have various hunches, but I'm running out of them, so if someone who knows about this stuff can give me any leads I would be very grateful.

Norm

1

There are 1 answers

0
Norman Birkett On

@panta rei: You provided the key in your comment. (Sorry, can't figure out how to type Greek letters here.)

The problem was basically that I didn't know how to tell Visual Studio what objects to link in. I had told my solution that AnalyticsUTest depended on AnalysticsUTested, but the linking step is performed by the project (AnalyticsUTest), not the solution, so I needed to tell the project to include this .lib file.

So I went to the project's properties sheet and created two new macros, one giving the folder where VS was putting my .lib file (ANALYTICSUTESTED_LIB_PATHS), the other giving the name of my .lib file (ANALYTICSUTESTED_LIB_DEPENDENCIES) -- both by analogy with the CPPUTEST_LIB* macros.

And then I added $(ANALYTICSUTESTED_LIB_PATHS) to Linker > General > Additional Library Directories. And I added $(ANALYTICSUTESTED_LIB_DEPENDENCIES) to Linker > Input > Additional Dependencies.

And that fixed my problem! (I've spelled it out here in case another newbie like me comes along and needs it.)

Thank you, panta rei. How do I give you points for an answer provided via a comment?