ld: дублированный символ. г ++ - PullRequest
0 голосов
/ 08 октября 2010

Хорошо, я пытаюсь разобраться с g ++ и библиотеками. У меня есть несколько файлов, которые я собрал в библиотеку

из файла make

$(CC) -fPIC -c -o $@ $< -O2 -D__PS2

тогда

$(CC) -shared -o $@ $(OBJ_FILES) -O2 -D__PS2

это прекрасно компилируется.

из программы, использующей lib

$(CC) -c -o $@ $< -I./

прекрасно компилируется

$(CC) -o $@ $(OBJ_FILES) I./ -Llib -mootPS2lib.so

Соединение объекта вместе, и оно идет БУМ!

ld: дубликат символа Moot :: loggerInstance () в object_files / foo.o и object_files / main.o

foo.hpp

//include guards
#include <Moot/Logger.hpp>
class Foo
{
public:
    void show();
}

foo.cpp

 #include "Foo.hpp"
 void Foo::show() { Moot::loggerInstance().turnLoggerOn(true); }

main.cpp включает только foo и вызывает метод show.

Спасибо за любую помощь.

UPDATE Извините, подробности вопроса мне не совсем понятны.

У меня это работает на Windows, сделав его статической библиотекой.

Logger.hpp выглядит следующим образом. * Это не совсем закончено, поэтому я знаю, что некоторые вещи отсутствуют. но это работает.

#ifndef MOOT_LOGGER_HPP
#define MOOT_LOGGER_HPP

#include <Moot/Platform.hpp>
#include <Moot/Utilities.hpp>
#include <iostream>
#include <fstream>
#include <string>

namespace Moot
{
    //! Outputs info to a text file. By default the logger is off.
    //! On the PS2 cout is used to output info onto the screen.
    class Logger
    {
        Logger()
        {
            std::ofstream logfile;
            logfile.open ("logfile.txt", std::ios::trunc);
            logfile << "LogFile - most recent at the bottom\n";
            logfile << "-----------------------------------\n \n";
            logfile.close();

            m_isLoggerOn = false;
        }


        Logger(const Logger&);
        Logger& operator=(const Logger&);

        ~Logger() {}

        bool m_isLoggerOn;

        template <typename T>
        void logMessage(T type)
        {
            # if (MOOT_ON_PS2)
                std::cout << type;
            # else
                std::ofstream logfile;
                logfile.open ("logfile.txt", std::ios::in | std::ios::app);
                logfile << type;
                logfile.close();
            #endif
        }


        //! Overiden << to allow you string together types.
        template <typename T>
        Logger& operator<< (T type) 
        {
            if (m_isLoggerOn) logMessage(type);

            return *this;
        }


        //! Overiden << to allow you string together types.
        Logger& operator<< (std::wstring wideStr)
        {
            if (m_isLoggerOn) logMessage(Moot::Utilities::convertWstringToString(wideStr));

            return *this;
        }

    public:

        //! Instance of the logger.
        static Logger& getInstance()
        {
            static Logger log;
            return log;
        }

        //! Switch Logging off or on. It is set to off by default.
        void turnLoggerOn(bool setLogger)
        {
            m_isLoggerOn = setLogger;
        }

    }; // Logger


    Logger& loggerInstance()
    {
        return Logger::getInstance();
    }


    //! Convenience variables
    namespace {
        Logger& lStart    = loggerInstance();
        const char lEnd   = '\n';
    }
} // Moot


#endif

Ответы [ 4 ]

2 голосов
/ 08 октября 2010

Решение - объявить loggerInstance встроенным.

Это реальное использование ключевого слова inline. Ваша функция будет встроена, если пожелает компилятор, но она не будет определена дважды.

0 голосов
/ 08 октября 2010

Убедитесь, что ваши заголовки включены только один раз. т.е.

#ifndef M_H
#define M_H
//Your code
#endif

Сдается мне, что есть двойное включение заголовка.

0 голосов
/ 08 октября 2010

Не похоже, что вам действительно нужно включить Logger.hpp в ваш Foo.hpp.Попробуйте включить его в Foo.cpp, где фактически используется объект Logger.

Как правило, не включайте вещи в заголовки, если только вам это абсолютно не нужно, так как это может создать зависимости, которые не нужны.будь там.Т.е.

foo.hpp

#ifndef FOO_HPP
#define FOO_HPP

class Foo 
{ 
public: 
    void show(); 
}

#endif // FOO_HPP

foo.cpp

 #include "Foo.hpp" 
 #include <Moot/Logger.hpp>
 void Foo::show() { Moot::loggerInstance().turnLoggerOn(true); } 
0 голосов
/ 08 октября 2010

Я ожидаю, что у вас есть что-то подобное в вашем файле logger.h:

namespace Moot
   {
   LoggerInstance &loggerInstance()
      {
      static LoggerInstance myself:
      return myself;
      }
   }

Это распространенный подход для реализации синглтона (хотя и не полностью поточно-ориентированный).

Решение состоит в том, чтобы переместить реализацию loggerInstance в отдельный файл .CPP.

...