PDA

View Full Version : Deploying an app with additional library



kornicameister
9th July 2011, 10:30
I am getting back to work on my project and as the first thing I would like to make it able to use additional library placed in external dll file. In other words I am trying to deploy dynamic linked application.

Unfortunately, after reading several different articles and threads I am a little bit confused about what I should do.

http://doc.qt.nokia.com/4.7-snapshot/sharedlibrary.html
http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++

Currently I am reading these two articles and I already know that I should focus on shared libraries because they are in fact DLL (or rather DLL are Microsoft's idea for that).

And to the project itself, I am adding now chunks of the code as mentioned in the first article in this paragraph -> "In each header of the library, we specify the following:".

By the way I am already having dll file. But I assume my Qt is statically built and somehow I remember that it is impossible to make dynamically linked application when using Qt built like this, am I right ?

kornicameister
9th July 2011, 20:18
Nevermind, this is about the previous post I wrote.

I have my program compiled with qmake, and I just found in documentation that the only way to add library to it is to make static library (just look for "Adding libraries in qmake projects" in Google, I found it via assistant built in QtCreator). From that comes my question.

Static library requires rebuilding whole application, when adding new functionality, or updating the library, to the library. Is this statement correct ? Because I am pretty sure that dynamic linked libraries do not require it, when adding some new functionality to library I am bound only to deploy new version of the dll file, right ?

All these question comes from my confusion, as I have spent whole day reading about it and trying to explain it by myself. And I am just trying to help myself to provide updates to the application not by recompiling it but by releasing new versions of my library.

Talei
9th July 2011, 20:28
Yes with statically compiled program compiler tends (actually must) to recompile everything, even if only small portion of small dll was changed. Of course you can use precompiled headers etc.. to speed that process up.
In dynamic linked program "You actually end up" with program + program (dll) and if You extend functionality in function that program uses in Your dll then You only need to recompile dll <- that's the key concept of dll, to have easy ability to update program for new functionality "fast" (in sense of compiling time) - also this saves memory, because dll is loaded only when it's needed.

kornicameister
9th July 2011, 20:49
so actually I need to do what ?
because honestly, at the moment, I do not know :)

The documentation shows qmake handled project to be used only with statically linked libraries, so do I need to change compiler ?

Talei
9th July 2011, 21:24
That depends on what You want to do :).

No You don't need to change compiler.

If You wrote Your dll and want it to be linked statically into the program code then add it into project file (.pro) like this:

LIBS += -L/path/to/lib -lLibName
and use exposed function (include .h file with function definition) from within your program. Then use class from the library as any other class.

If You want it to be dynamically linked then use QLIbrary and load library at particular time, when function from library is needed, something along these lines:

void myClass::doSomething() {
QLibrary tessLib("qLibT.dll");
tessLib.load();

if( tessLib.isLoaded() )
{
qDebug() << "Lib loaded succesful: " << tessLib.errorString();
}else{
qDebug() << "Error lib load: " << tessLib.errorString();
return false;
}

tessDllBeginPage = (TessDllBeginPage) tessLib.resolve( "TessDllBeginPage" );

if(tessDllBeginPage){
qDebug() << "tessDllBeginPage useful!!! GOOD" << tessLib.errorString();
}else{
qDebug() << "tessDllBeginPage not resolved!" << tessLib.errorString();
return false;
}
}

kornicameister
9th July 2011, 22:02
but in Your example You are trying to resole particular method, right ?
How about creating an object of the class defined and declared in the library ?

Talei
9th July 2011, 22:40
In above example I resolve functions from dll in i.e. constructor of my main program class (i.e. void myProgramMainClass::initLib() ).

tessDllBeginPage = (TessDllBeginPage) tessLib.resolve( "TessDllBeginPage" );
tessDllBeginPage is of type TessDllBeginPage* and declared in private section of this class, so I can use tessDllBeginPage anywhere in my class.
Usage:
.h private section

typedef int (*TessDllBeginPageUprightBPP)(uinT32 xsize,
uinT32 ysize,
unsigned char *buf,
const char* lang,
uinT8 bpp);
TessDllBeginPageUprightBPP tessDllBeginPageUprightBPP;
.cpp use function from dll

qDebug() << tessDllBeginPageUprightBPP( (uinT32)tmpPix.width(), (uinT32)tmpPix.height(),
tmpPix.bits(),
"eng",
(uinT8)tmpPix.depth() );
I posted different function (I actually didn't use earlier posted) but You will get basic idea how to use it.
Or, to answer your question, example with popler dll:
.pro file

LIBS += -llibpoppler-qt4
.h private

Poppler::Document *document;
.cpp

Poppler::Document *pdfDoc = Poppler::Document::loadFromData( baPdf );

See this, that will help you:
http://doc.qt.nokia.com/qtcreator-2.2/creator-project-qmake-libraries.html

kornicameister
10th July 2011, 09:22
so all I need to do is to exposed the constructor with proper macro, not the class itself,
like here (http://doc.qt.nokia.com/latest/sharedlibrary.html) ?

and load the library right before creating the object of the class...

I am going to try it :)

one more question about "Typically, clients will include only the public header files of shared libraries." -
the public header is the one without _global suffix ? I created the shared library project using wizard in qt and it made for me 2 headers:
- mylib.h
- mylib_global.h

and and the tutorial says about including the public header of the library, but I assume it is the one without global at the end.

Nevertheless I was given with the link about adding libraries to the project...but...the only file I can add are those with the .lib extension....the problem is I have no such file created after compiling the library...all I have are .a and .dll file

kornicameister
10th July 2011, 15:51
alright it's time to get out from confusion...
I still can not get all working, but after constantly reading and reading, I found this article http://developer.qt.nokia.com/forums/viewthread/6433

basing on it, what I need is to have something usable like for example usage of mysql in qt projects, where I include one some headers but basically I need to deliver an dll to release version ? But I am afraid it may consider plugins...but I will not verify here anything, because I lost all clear thinking

hope that will make my idea more clear...because honestly web is full of different approaches which differs from each other and I do not know what to do know, even the help which Talei has offered was not really helpful because clearly even me don't understand how it should works.

Nevertheless my goal is as presented above...and I only need some guidance.
Basically I know I will have to provide some headers to the client. But let's focus on the library itself. So far, I've created the shared library project in qt creator...very simple, just for educational purpose :)

the codes

TestProjectLib.pro

#-------------------------------------------------
#
# Project created by QtCreator 2011-07-10T11:40:27
#
#-------------------------------------------------

QT -= gui

TARGET = TestProjectLib
TEMPLATE = lib
CONFIG += dll #added manually

DEFINES += TESTPROJECTLIB_LIBRARY

SOURCES += testprojectlib.cpp \
summator.cpp

HEADERS += testprojectlib.h\
TestProjectLib_global.h \
summator.h

symbian {
#Symbian specific definitions
MMP_RULES += EXPORTUNFROZEN
TARGET.UID3 = 0xE14FD6C2
TARGET.CAPABILITY =
TARGET.EPOCALLOWDLLDATA = 1
addFiles.sources = TestProjectLib.dll
addFiles.path = !:/sys/bin
DEPLOYMENT += addFiles
}

unix:!symbian {
maemo5 {
target.path = /opt/usr/lib
} else {
target.path = /usr/local/lib
}
INSTALLS += target
}


TestProjectLib.h



#ifndef TESTPROJECTLIB_H
#define TESTPROJECTLIB_H

#include "TestProjectLib_global.h"

class TESTPROJECTLIBSHARED_EXPORT TestProjectLib {
public:
TestProjectLib();
};

#endif // TESTPROJECTLIB_H


TestProjectLib_global.h

#ifndef TESTPROJECTLIB_GLOBAL_H
#define TESTPROJECTLIB_GLOBAL_H

#include <QtCore/qglobal.h>

#if defined(TESTPROJECTLIB_LIBRARY)
# define TESTPROJECTLIBSHARED_EXPORT Q_DECL_EXPORT
#else
# define TESTPROJECTLIBSHARED_EXPORT Q_DECL_IMPORT
#endif

#endif // TESTPROJECTLIB_GLOBAL_H


and I have an additional class where I put some trivial functionality



#ifndef SUMMATOR_H
#define SUMMATOR_H

#include <QObject>
#include <TestProjectLib_global.h>

class TESTPROJECTLIBSHARED_EXPORT Summator : public QObject
{
Q_OBJECT
public:
explicit TESTPROJECTLIBSHARED_EXPORT Summator(QObject *parent = 0);

double TESTPROJECTLIBSHARED_EXPORT summatorMe(int loops, int number);
private:
int loops;
};

#endif // SUMMATOR_H


this concept presents the concept I want to use the library in my application, which means creating the class' objects like this

MyClass *obj = new MyClass()
and not by using some weird constructions with QLibrary

maybe this can help us to help me :)