PDA

View Full Version : Using content from a dynamic library (Windows)



MasterBLB
8th August 2011, 13:23
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:

#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__,l evel);
#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:

#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);
Logger(QObject *parent=0);

public:
static LoggerObject* getLoggerObject(const QString &id);
static void printLog(const QString &text,const QString &loggerID,int line=0,const QString &file=QString(),char level=maxLevel,char type=0);

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);
LoggerObject(const QString &id,QObject *parent)
:QObject(parent),id(id),logFile(id+".log.xml"),mode(Window)
{};

public:
QString identifier(void);
void setLogMode(LogMode mode);
LogMode logMode(void);
void setLogFile(const QString &filename);
QString logFileName(void);

//co jeszcze trzeba
};
#endif // LOGGER_H

Dong Back Kim
9th August 2011, 01:51
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,

MasterBLB
9th August 2011, 09:38
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

wysota
9th August 2011, 12:56
You need to #include "logger.h" in your program.

MasterBLB
9th August 2011, 13:28
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

wysota
9th August 2011, 13:37
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).

MasterBLB
9th August 2011, 14:06
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

#define LOGDEBUG_Logger(text,loggerId,level) Logger::printLog(text,loggerId,__LINE__,__FILE__,l evel);
use something like:

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:

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);

wysota
9th August 2011, 14:14
Export the logPrint function (using LOGGER_EXPORT or whatever).

MasterBLB
9th August 2011, 14:32
HELLL YEAH!All works!
Big thanks to you Wysota :)