0

I just don't understand why i can use the public variables on the class but are getting a link error when trying to use the getLicenceRefused method. I wasn't sure if the problem was because of the CString copy constructor problem I have had before so took the parameter out, but i still got the same error.

So the class is being compiled and linked (as I can use the member variables) it is when i try to call any of the functions I get this error.

I have tried to be as comprehensive as possible sorry if I have missed something important or have included too much.

I only do c++ sporadically (so sorry if my terminology is java based) as it is maintaining old code and nobody here uses c++ enough to maintain their skill level. Both classes are internal classes (written by people who have now left :) ), both classes are in different projects in the same solutions. the ConfigurationDialog project depends upon the CServerSettings project. Here is my calling code

int CConfigurationDialog::testConnection(CString connectionName, CString origin)
{
  CServerConnection* connection = getConnection();

  // these 2 lines of code work and return the correct result, it is the body of the function with problems
  auto result = connection->m_licencesRefused.find(origin);
  bool connRefused =  (result != connection->m_licencesRefused.end());

  if(connection->getLicenceRefused(origin)) // this is the line with the link error

the class definition

class CServerConnection
{
    public:
        CServerConnection();
        CServerConnection( LPCTSTR connectionName );

        void setLicenceRefused(CString origin, bool value);
        bool getLicenceRefused(CString origin);
        void setLicenceRequested(CString origin, bool value);
        bool getLicenceRequested(CString origin);
        void clearAllLicences();
        CString getLoggedOnOrigin();
        void setURLNotFound(bool notFound);
        bool getURLNotFound();

    public:
        bool m_initialised;
        CString m_connectionName;
        CString m_lastError;
        CString m_password;
        CString m_company;
        CString m_username;
        CString m_sessionID;

    public:
        std::set<CString> m_licencesRefused;

        bool m_urlNotFound;
};

the class body (i can't include the whole file as it is over 1000 lines and includes several classes):

CServerConnection::CServerConnection(LPCTSTR connectionName)
{
    m_initialised = false;
    m_connectionName = connectionName;
    m_lastError = _T( "" );
    m_urlNotFound = false;
}

CServerConnection::CServerConnection()
{
    m_initialised = false;
    m_connectionName = _T( "" );
    m_lastError = _T( "" );
    m_urlNotFound = false;
}

void CServerConnection::setLicenceRefused(CString origin, bool value)
{
    if(value)
    {
        m_licencesRefused.insert(origin);
    }
    else
    {
        m_licencesRefused.erase(origin);
    }
}

bool CServerConnection::getLicenceRefused(CString origin)
{
    auto result = m_licencesRefused.find(origin);
    return (result != m_licencesRefused.end());
}

void CServerConnection::setLicenceRequested(CString origin, bool value)
{
    if(value)
    {
        m_licencesRequested.insert(origin);
    }
    else
    {
        m_licencesRequested.erase(origin);
    }
}

bool CServerConnection::getLicenceRequested(CString origin)
{
    auto result = m_licencesRequested.find(origin);
    return (result != m_licencesRequested.end());
}

void CServerConnection::clearAllLicences()
{
    m_licencesRefused.clear();
    setLicenceRefused(XL_FINANCE_ORIGIN, false);
    setLicenceRefused(XL_POP_ORIGIN, false);

    m_licencesRequested.clear();
    setLicenceRequested(XL_FINANCE_ORIGIN, false);
    setLicenceRequested(XL_POP_ORIGIN, false);
}

CString CServerConnection::getLoggedOnOrigin()
{
    if(getLicenceRequested(XL_FINANCE_ORIGIN) && !getLicenceRefused(XL_FINANCE_ORIGIN))
    {
        return XL_FINANCE_ORIGIN;
    }

    if(getLicenceRequested(XL_POP_ORIGIN) && !getLicenceRefused(XL_POP_ORIGIN))
    {
        return XL_POP_ORIGIN;
    }

    return _T("");
}

void CServerConnection::setURLNotFound(bool notFound)
{
    m_urlNotFound = notFound;
}

bool CServerConnection::getURLNotFound()
{
    return m_urlNotFound;
}

and the error:

 error LNK2019: unresolved external symbol "public: bool __thiscall CServerConnection::getLicenceRefused(class ATL::CStringT<wchar_t,class StrTraitMFC_DLL<wchar_t,class ATL::ChTraitsCRT<wchar_t> > >)" (?getLicenceRefused@CServerConnection@@QAE_NV?$CStringT@_WV?$StrTraitMFC_DLL@_WV?$ChTraitsCRT@_W@ATL@@@@@ATL@@@Z) referenced in function "private: int __thiscall CConfigurationDialog::testConnection(class ATL::CStringT<wchar_t,class StrTraitMFC_DLL<wchar_t,class ATL::ChTraitsCRT<wchar_t> > >,class ATL::CStringT<wchar_t,class StrTraitMFC_DLL<wchar_t,class ATL::ChTraitsCRT<wchar_t> > >)" (?testConnection@CConfigurationDialog@@AAEHV?$CStringT@_WV?$StrTraitMFC_DLL@_WV?$ChTraitsCRT@_W@ATL@@@@@ATL@@0@Z)
WendyG
  • 570
  • 5
  • 29
  • Please provide CServerConnection class implementation. – Ari0nhh Jun 22 '15 at 16:54
  • possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – Ken White Jun 22 '15 at 17:06
  • i want to know why i can see/use the class member variables but not the methods, which doesn't seem to be covered anywhere just how to ensure all the files are included and about getting the correct method signatures. – WendyG Jun 22 '15 at 17:07
  • are CConfigurationDialog and CServerConnection defined in different libraries? structure of your project is very important in this case – luantkow Jun 22 '15 at 17:11
  • Both classes are internal classes (written by people who have now left :) ), both classes are in different projects in the same solutions. the ConfigurationDialog project depends upon the CServerSettings project. – WendyG Jun 22 '15 at 17:18
  • and CServerSettings project contains file that defines CServerConnection::getLicenceRefused (i.e. CServerConnection.cpp)? – luantkow Jun 22 '15 at 17:23
  • If you include that header...how can compiler know that compilation unit is in another project? More: it does not know that code is already compiled and resides in another dll. Check an example for dllexport and dllimport. – Adriano Repetti Jun 22 '15 at 17:27

1 Answers1

1

The header file provides enough information to let you declare variables. And for that matter to just compile (but not link) code. When you link, the linker has to resolve e.g. function references such as a reference to ServerConnection::getLicenceRefused, by bringing in the relevant machine code.

You have to tell the linker which library or object file to link with to bring in that machine code.

The lowercase first letter in getLicenseRefused indicates that it's not Microsoft code, although it could maybe be a property accessed from C++. Unless someone familiar with that should happen to see this and respond, you'll have to figure out the library or object file yourself. Usually this involves looking at documentation, but depending on circumstances it might be as simple as adding a .cpp file to the project; whatever.


Addendum: After I wrote the above the OP has provided source code for the class.

So possibly this involves just adding that .cpp file to the project.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • so the header file provides enough info to see/ use variables but not methods? I needed to add __declspec(dllexport) to the class, no idea what it means, but i remember it from last time i ventured into this world. Thank you everyone. – WendyG Jun 22 '15 at 17:20