c++lnk2019unresolved-externalobject-files

c++ error LNK2019: unresolved external symbol .obj


First of all, I know there are over a hundred similar posts out there with the same error, and the entire reason for that is because the error given is as useless as can be..

I've searched through over 20 solutions already through Google and I still can't figure out where the error is in my code, so therefore I'm making this question.

Here is the error:

Error   2   error LNK1120: 1 unresolved externals   C:\Users\Kevin Cruijssen\Documents\Visual Studio 2013\Projects\ClientOSCPP-trunk\ cpp-and-so-client\ClientOSCPP\Debug\ClientOSCPP.exe   ClientOSCPP

Error   1   error LNK2019: unresolved external symbol "private: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall CommandSyncHandler::FileJustRenamed(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?FileJustRenamed@CommandSyncHandler@@AAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V23@@Z) referenced in function "private: void __thiscall CommandSyncHandler::ReadFilesToSync(class Socket *)" (?ReadFilesToSync@CommandSyncHandler@@AAEXPAVSocket@@@Z)    C:\Users\Kevin Cruijssen\Documents\Visual Studio 2013\Projects\ClientOSCPP-trunk\ cpp-and-so-client\ClientOSCPP\CommandSyncHandler.obj  ClientOSCPP

And here are the classes that the error is occurring in:

CommandSyncHandler.h:

#pragma once

#include "CommandHandler.h"

class CommandSyncHandler : public CommandHandler
{
private:
    CommandSyncHandler(void);
    CommandSyncHandler(const char* szCommand);

    static CommandSyncHandler m_cSyncHandler;
    std::string localFolder, remoteFolder;

    std::string FileJustRenamed(std::string filename);

    void ReadFilesToSync(Socket* socket);

public:
    virtual ~CommandSyncHandler(void);

    virtual CommandHandler* Clone() const;

    virtual void HandleCommand(Socket* socket, std::vector<std::string>& rvParams);
};

CommandSyncHandler.cpp:

#include "stdafx.h"

#include "CommandSyncHandler.h"
#include "Constants.h"
#include "FileReader.h"
#include "FileHandler.h"
#include "CommandFactory.h"

#include <iostream>
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <time.h>

CommandSyncHandler CommandSyncHandler::m_cSyncHandler("SYNC");

CommandSyncHandler::CommandSyncHandler(const char* szCommand) : CommandHandler(szCommand){}

CommandSyncHandler::CommandSyncHandler(void){}

CommandSyncHandler::~CommandSyncHandler(void){}

CommandHandler* CommandSyncHandler::Clone() const{
    return new CommandSyncHandler;
}

std::string FileJustRenamed(std::string filename){
    std::string result = "";

    /*std::string filedir;
    const size_t last_slasg_index = filename.rfind(PATH_SEPARATOR);
    if (std::string::npos != last_slasg_index)
        filedir = filename.substr(0, last_slasg_index);
    filedir = SERVER_DIRECTORY + filedir.substr(BASE_DIRECTORY.length());

    // First check wether the file is the exact same size 
    // before continueing to compare the bytes/md5-hashes (which takes longer)
    FileReader* reader1;
    try{
        reader1 = new FileReader(filename.c_str());
    }
    catch (const char* e){
        (void)e;

        std::cout << "Cannot open file: " << filename << std::endl;
        return result = "";
    }
    int size1 = reader1->FileSize();

    // Loop through all the files in the Server's same Directory
    FileHandler fileHandler;
    std::vector<std::string> filesInDir;
    fileHandler.GetFiles(filedir.c_str(), filesInDir);
    for each (std::string curfile in filesInDir) {
        bool continueLoop = true;

        FileReader* reader2 = NULL;
        try{
            reader2 = new FileReader(curfile.c_str());
        }
        catch (const char* e){
            (void)e;

            std::cout << "Cannot open file: " << filename << std::endl;
            continueLoop = false;
        }

        if (continueLoop){
            int size2 = reader2->FileSize();

            if (size1 != size2){
                result = "";
                continueLoop = false;
            }

            if (continueLoop){
                // If the size of both files are the same, we continue to check if they are the exact same file
                // We do this by comparing the byte-blocks of the file-buffer
                const int BUFFER_SIZE = 1024;

                std::ifstream file1(filename.c_str(), std::ios::in | std::ios::binary);
                std::ifstream file2(curfile.c_str(), std::ios::in | std::ios::binary);

                if (!file1.good() || !file2.good()){
                    result = "";
                    continueLoop = false;
                }

                if (continueLoop){
                    std::streamsize bytesCount1 = 0;
                    std::streamsize bytesCount2 = 0;
                    char* buffer1 = new char[BUFFER_SIZE]();
                    char* buffer2 = new char[BUFFER_SIZE]();

                    do {
                        file1.read(buffer1, BUFFER_SIZE);
                        file2.read(buffer2, BUFFER_SIZE);
                        bytesCount1 = file1.gcount();
                        bytesCount2 = file2.gcount();

                        if (bytesCount1 != bytesCount2 || std::memcmp(buffer1, buffer2, bytesCount1) != 0)
                            continueLoop = false;
                    } while (file1.good() || file2.good());

                    if (continueLoop)
                        return curfile;
                }
            }
        }
    }*/

    return result = "";
}

void CommandSyncHandler::HandleCommand(Socket* socket, std::vector<std::string>& rvParams){
    if (rvParams.size() < 3)
        throw "Not enough parameters specified";

    localFolder = rvParams.at(1);
    remoteFolder = rvParams.at(2);
    std::string filePath = BASE_DIRECTORY;
    filePath.append(localFolder);

    rvParams.erase(rvParams.begin() + 1);
    std::string command = BuildCommand(rvParams);
    socket->writeline(command.c_str());

    /*| TODO
    struct stat file_stats;
    struct tm* clock;
    stat(filePath.c_str(), &file_stats);
    clock = gmtime(&(file_stats.st_mtime));
    mktime(clock);
    */

    std::vector<std::string> vFiles;
    std::string directory = BASE_DIRECTORY;
    directory.append(localFolder);

    FileHandler handler;
    handler.GetFiles(directory.c_str(), vFiles);

    for (std::string file : vFiles){

        file.erase(0, BASE_DIRECTORY.size());
        //Translate local folder to remote folder to sync
        int index = file.find(localFolder);
        if (index >= 0){
            file.erase(index, localFolder.size());
            file.insert(index, remoteFolder);
        }
        socket->writeline(file.c_str());
    }
    socket->writeline("");
    //std::string file = remoteFolder;
    //file.append(PATH_SEPARATOR);
    //file.append(ent->d_name);
    //socket->writeline(file.c_str());

    ReadFilesToSync(socket);
}

void CommandSyncHandler::ReadFilesToSync(Socket* socket){
    char* returnFile = new char[MAXPATH + 1];
    char* returnLine = new char[MAXREAD + 1];
    CommandHandler* handler = CommandFactory::create("PUT");

    std::vector<std::string> vFiles;
    while (socket->readline(returnFile, MAXPATH) > 0)
        vFiles.push_back(std::string(returnFile));

    for (std::string remoteFile : vFiles){
        std::string file = remoteFile;
        //Translate remote folder to local folder to sync
        int index = file.find(remoteFolder);

        std::vector<std::string> vParams;
        // Check wether file is completely different or just renamed
        std::string oldFile = FileJustRenamed(file);
        if (oldFile != "") {
            vParams.push_back(std::string("REN"));
            vParams.push_back(oldFile);
            vParams.push_back(file);
        }
        else {
            // Replace file
            if (index >= 0){
                file.erase(index, remoteFolder.size());
                file.insert(index, localFolder);
            }

            vParams.push_back(std::string("PUT"));
            vParams.push_back(file);
            vParams.push_back(std::string(remoteFile));
        }

        std::cout << "Sending " << file << std::endl;
        handler->HandleCommand(socket, vParams);

        // Read feedback from put command
        while (socket->readline(returnLine, MAXREAD) > 0)
            std::string x = returnLine;//std::cout << returnLine << std::endl;
    }

    delete handler;
    delete[] returnFile;
    delete[] returnLine;

    throw "Sync completed";
}

Anyone has any idea? Because after more than 2 hours I really want this fixed so I can continue with this crappy project..

PS: Everything in the function FileJustRenamed is commented out, so I know the error isn't somewhere in that code.

PSS: Ignore the bad programming.. I'm kinda new to C++.

PSSS: Everything worked before the FileJustRenamed part was added in both the .h and .cpp files and in the ReadFilesToSync function.

Some things I tried:

I probably just made a small mistake like the order of functions in the header/cpp files or something small forgotten to add (like an include), but like I said, after more than 2 hours I really have block-eyes and don't have any clue how to fix it..

So please help.. Thanks in advance.


Solution

  • In "CommandSyncHandler.cpp", in the definition of the function FileJustRenamed() prepend the class-name CommandSyncHandler to the function name, like this:

    std::string CommandSyncHandler::FileJustRenamed(std::string filename){