1

Today I encountered a liking problem with static variable/function. First let me show you the code:

Trace.h

class Trace : public QObject
{
    Q_OBJECT

public:
    explicit Trace(QObject *parent = 0);
    static void setLogFilePath(QString path)
    {
         logFilePath = path;
    }
    QString getLogFilePath();

private:
    static QString logFilePath;
};

#endif // TRACE_H

Trace.cpp

// includes.. constructors..

QString Trace::getLogFilePath()
{
    return logFilePath;
}

On Linux, I can compile this class to generate a dynamic library without any problem. On windows, I can't, I have an undefined reference to logFilePath.

I know that with TEMPLATE = app I have to define my static variables in the main, but with a library I don't think so but I'm not sure.

I saw that on windows, if put the implementation in the header file like this:

Trace.h

QString Trace::getLogFilePath()
{
     return logFilePath;
}

There is no liking error.

1) Why is there a difference like this between Linux and Windows ? (Same Qt version).

2) Is using static variable in dynamic library a good thing or not ? (I can overcome this problem with a file, maybe it's better).

Thanks in advance.

Martin
  • 877
  • 8
  • 20
  • 2
    Add `QString Trace::logFilePath = QString();` to your .cpp file. – vahancho Jun 30 '14 at 11:33
  • QString Trace::logFilePath; in .cpp file works, thanks. However I'm really curious to know why you need this on windows and why not on linux. – Martin Jun 30 '14 at 11:38
  • 1
    In Linux you probably get linker error building executable with this library. Library is allowed to have unresolved references. – Alex F Jun 30 '14 at 11:40
  • 1
    It might also be an inconsistency. With some compiler version, I observed that the defintion (for a `static unsigned`) in the .cpp file had to be there for the gcc, but caused a linker error with the Microsoft compiler... – Sedenion Jun 30 '14 at 11:45
  • @AlexFarber It's on Windows I have a linker error. Just checking my command line and I don't try to build any executable. – Martin Jun 30 '14 at 11:50

1 Answers1

4

The problem with the linking is in both, the logFilePath variable and the getLogFilePath() function.

When you have moved the function from the .cpp file to the header file, then you have placed all the class in the header file, making it available to any compilation unit. Doing this you are NOT using the dynamic library, you are just using your class definition found in the header file.

In order to be able to generate a dynamic library with your class hidden in the .cpp file, and only having available the header file, you need to tell the linker to "search the class in external libraries". This is done by including the __declspec(dllexport) and __declspec(dllimport) to the class definition.

You have more information here: How to implement a class counter in DLL?

Also, ALL the static variables MUST be instantiated somewhere outside de .h file. This is done, as stated by vahancho, by declaring it in the .cpp file. It is not requiered to be the main.cpp file, it should be the .cpp file corresponding to your class definition file.

Best regards, Ruben

Community
  • 1
  • 1
LoPiTaL
  • 2,495
  • 16
  • 23