Using content from a dynamic library (Windows)
Hi All
I'm developing my own logger project.I wish it to be an external .dll file added to other project,without need of compilation or somesuch.
I've created some test project,added logger.lib to linker libs,copied logger.dll into my test project-but it does not work when I try to use one of my macros :/
What else shoud be done to make it work?To use QLibrary::resolve()?
Below my header files:
Code:
#ifndef LOGGER_GLOBAL_H
#define LOGGER_GLOBAL_H
#include <Qt/qglobal.h>
#define maxLevel 4
#ifdef LOGGER_LIB
# define LOGGER_EXPORT Q_DECL_EXPORT
#else
# define LOGGER_EXPORT Q_DECL_IMPORT
#endif
#define LOGDEBUG_Logger(text,loggerId,level) Logger::printLog(text,loggerId,__LINE__,__FILE__,level);
#define LOGDEBUG_Level(text,level) LOGDEBUG_LOGGER(text,"default",level)
#define LOGDEBUG(text) LOGDEBUG_Logger(text,"default",maxLevel)
#endif // LOGGER_GLOBAL_H
and logger.h file:
Code:
#ifndef LOGGER_H
#define LOGGER_H
#include <QMap>
#include <QObject>
#include "logger_global.h"
#include "logwindow.h"
LOGGER_EXPORT enum LogMode
{
None=0,
Window,
File,
WindowAndFile
};
class LoggerObject;
class LOGGER_EXPORT Logger
: public QObject{
QMap<QString,LoggerObject*> loggers;
static Logger *instance;
LoggerObject *defaultLogger;//for convience and to avoid getting it from the map all the time
static inline bool createManager(void);
public:
static LoggerObject
* getLoggerObject
(const QString &id
);
virtual ~Logger(void);
};
class LOGGER_EXPORT LoggerObject
: public QObject{
friend class Logger;
QList<LogData> logs;//contains log messages.Filled by Logger::printLog()
QString id;
//identifier of logger in Logger::loggers map LogMode mode;//determines where the logs shoud be put in
QString logFile;
//name and path of the log file LogWindow *logWindow;
void printLog
(const QString &text,
int line
=0,
const QString &file
=QString(),
char level
=maxLevel,
char type
=0);
:QObject(parent
),id
(id
),logFile
(id
+".log.xml"),mode
(Window
) {};
public:
void setLogMode(LogMode mode);
LogMode logMode(void);
void setLogFile
(const QString &filename
);
//co jeszcze trzeba
};
#endif // LOGGER_H
Re: Using content from a dynamic library (Windows)
Hi there,
can you specify more about your problem? when you say "it doesn't work", what do you mean by it? compile error (if so what error message)? runtime error?
Regards,
Re: Using content from a dynamic library (Windows)
Sorry,I forgot to add compilation errors:
loggerdlltest.cpp(7) : error C2653: 'Logger' : is not a class or namespace name
loggerdlltest.cpp(7) : error C3861: 'printLog': identifier not found, even with argument-dependent lookup
Re: Using content from a dynamic library (Windows)
You need to #include "logger.h" in your program.
Re: Using content from a dynamic library (Windows)
Mhm...so even having a *.dll and appropriate *.lib file I have to provide all needed header files,right?Binary code shoud be inside .dll I assume,and if so there shoud be no need for .cpp's
Re: Using content from a dynamic library (Windows)
There is no need for cpp files but you need to provide the headers. I suggest you change your macros to functions. Then you'll only have to provide headers with prototypes of those functions and the implementation that uses the Logger class (together with the header for that class) can remain hidden (and then you don't have to expose the class using LOGGER_EXPORT).
Re: Using content from a dynamic library (Windows)
Quote:
Originally Posted by
wysota
I suggest you change your macros to functions. Then you'll only have to provide headers with prototypes of those functions and the implementation that uses the Logger class (together with the header for that class) can remain hidden (and then you don't have to expose the class using LOGGER_EXPORT).
I'd wish to do it that way,but I can't :/ all because of that __LINE__ and __FILE__,it has to be placed at the line of using a macro.
Hmmmm...or there is a solution,instead of
Code:
#define LOGDEBUG_Logger(text,loggerId,level) Logger::printLog(text,loggerId,__LINE__,__FILE__,level);
use something like:
Code:
void someGlobalFunction(params);//declaration there,definition inside let's say logger.cpp and therefore inside the .dll file
#define LOGDEBUG_Logger(text,loggerId,level) someGlobalFunction(text,loggerId,__LINE__,__FILE__,level);
and inside it I shoud invoke my Logger::printLog
Added after 14 minutes:
Well,thanks Wysota,that idea of using a global function instead of Logger::printLog helped to hide all the complexity.But now I have an issue with linker:
loggerdlltest.obj : error LNK2019: unresolved external symbol _logPrint referenced in function "public: __thiscall LoggerDLLTest::LoggerDLLTest(class QWidget *,class QFlags<enum Qt::WindowType>)" (??0LoggerDLLTest@@QAE@PAVQWidget@@V?$QFlags@W4Win dowType@Qt@@@@@Z)
C:\Program Files\Microsoft Visual Studio .NET 2003\Projects\LoggerDLLTest\Release\LoggerDLLTest. exe : fatal error LNK1120: 1 unresolved externals
How to make it work?I changed my file logger_global.h to:
Code:
extern "C" void __cdecl logPrint
(const QString &text,
const QString &loggerID,
int line
=0,
const QString &file
=QString(),
char level
=maxLevel,
char type
=0);
#define LOGDEBUG_Logger(text,loggerId,level) logPrint(text,loggerId,__LINE__,__FILE__,level);
Re: Using content from a dynamic library (Windows)
Export the logPrint function (using LOGGER_EXPORT or whatever).
Re: Using content from a dynamic library (Windows)
HELLL YEAH!All works!
Big thanks to you Wysota :)