0

What am I doing wrong? How to solve the linker error when trying to use the following class that inherits from basic_streambuf?

I am trying to use the example suggested here:
Redirect C++ std::clog to syslog on Unix

But I have a linker error: "undefined reference to `Log::Log(std::string, int)'"

[ERROR] /home/opmet/rgdias/pj_opmet/core/opmet-cpp/amhs-sender/target/nar/obj/amd64-Linux-gpp/main.63ebf91e.o: In function `main':
[ERROR] /home/opmet/rgdias/pj_opmet/core/opmet-cpp/amhs-sender/src/main/c++/main.cpp:52: undefined reference to `Log::Log(std::string, int)'

My code is doing something, like:

std::clog.rdbuf(new Log("foo", LOG_LOCAL0));

In order to use the class declared here:

#include <streambuf>
#include <syslog.h>
enum LogPriority {
    kLogEmerg   = LOG_EMERG,   // system is unusable
    kLogAlert   = LOG_ALERT,   // action must be taken immediately
    kLogCrit    = LOG_CRIT,    // critical conditions
    kLogErr     = LOG_ERR,     // error conditions
    kLogWarning = LOG_WARNING, // warning conditions
    kLogNotice  = LOG_NOTICE,  // normal, but significant, condition
    kLogInfo    = LOG_INFO,    // informational message
    kLogDebug   = LOG_DEBUG    // debug-level message
};

std::ostream& operator<< (std::ostream& os, const LogPriority& log_priority);

class Log : public std::basic_streambuf<char, std::char_traits<char> > {
public:
    explicit Log(std::string ident, int facility);

protected:
    int sync();
    int overflow(int c);

private:
    friend std::ostream& operator<< (std::ostream& os, const LogPriority& log_priority);
    std::string buffer_;
    int facility_;
    int priority_;
    char ident_[50];
};

#include <cstring>
#include <ostream>
#include "log.h"

Log::Log(std::string ident, int facility) {
    facility_ = facility;
    priority_ = LOG_DEBUG;
    strncpy(ident_, ident.c_str(), sizeof(ident_));
    ident_[sizeof(ident_)-1] = '\0';

    openlog(ident_, LOG_PID, facility_);
}

int Log::sync() {
    if (buffer_.length()) {
        syslog(priority_, "%s", buffer_.c_str());
        buffer_.erase();
        priority_ = LOG_DEBUG; // default to debug for each message
    }
    return 0;
}

int Log::overflow(int c) {
    if (c != EOF) {
        buffer_ += static_cast<char>(c);
    } else {
        sync();
    }
    return c;
}

std::ostream& operator<< (std::ostream& os, const LogPriority& log_priority) {
    static_cast<Log *>(os.rdbuf())->priority_ = (int)log_priority;
    return os;
}
Rodolfo
  • 149
  • 1
  • 9
  • 1
    You declared your constructor. Did you actually write it, maybe in a .cpp file? – jkb Jun 30 '20 at 01:47
  • `std::clog.rdbuf(new ...);` is a guaranteed way to leak memory – eerorika Jun 30 '20 at 01:52
  • I would appreciate if you guys focus on the actual error, rsrsrsrsrs. – Rodolfo Jun 30 '20 at 01:58
  • 1
    @jkb's comment is the answer. You declared a constructor but didn't implement it. – Miles Budnek Jun 30 '20 at 02:00
  • 2
    I am. If you did not actually write your constructor, or if you didn't include the source file on the compiler command line you will get that linker error. – jkb Jun 30 '20 at 02:00
  • If you did actually implement the constructor like in the linked solution then you are not building the source file that contains the implementation. – drescherjm Jun 30 '20 at 02:03
  • Now I see that omit the cpp was a huge mistake.I have copied the cpp. All the point is that the code is the same of the one used in a past thread. – Rodolfo Jun 30 '20 at 02:11
  • I am pretty sure the bug is how you are building this. – drescherjm Jun 30 '20 at 02:12
  • 1
    The dupe I flagged covers all of the possible causes of the error you're seeing. Since you have an implementation of the missing constructor that means you either aren't compiling that file or aren't linking to the compiled object file. – Miles Budnek Jun 30 '20 at 02:15
  • Seems to work here when I added all 3 files: [https://onlinegdb.com/Syl5e7_RU](https://onlinegdb.com/Syl5e7_RU) – drescherjm Jun 30 '20 at 02:17

0 Answers0