PDA

View Full Version : Including a self-made library into another project



jepessen
26th May 2011, 13:28
Hi.
I'm trying to create a program with one library and one executable that invokes that library.

At first, I've created one folder for the application, and then three subfolders, one for a test executable project, one for the library project and one that's the path in which both library and executable are copied.

APP
|
|- bin
|- MyLibrary
| |- MyLibrary <== .pro and sources
| |- MyLibrary-build-desktop
|- TestApp
| |- TestApp <== .pro and sources
| |- TestApp-build-desktop


This is the .pro of the library


QT -= gui
TARGET = MyLibrary
TEMPLATE = lib
DEFINES += MYLIBRARY_LIBRARY

SOURCES += mylibrary.cpp
HEADERS += mylibrary.h\
MyLibrary_global.h \

# Copying to destination folder
DESTDIR = ../../bin

This one is the .pro of the test application

QT += core
QT -= gui
TARGET = TestApp
CONFIG += console
CONFIG -= app_bundle

TEMPLATE = app
SOURCES += main.cpp
# MeteoGrid Library
LIBS += -L../../bin/libMyLibrary.so
INCLUDEPATH += ../../MyLibrary/MyLibrary


# Copying to destination folder
DESTDIR = ../../bin

When I compile the library, it's successfully copied into the bin directory.

If I include the mylibrary.h header into the test application, it finds it and it compiles.
But, if I try to use the class defined in my library


#include <QtCore/QCoreApplication>

#include "mylibrary.h"

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

MyLibraryClass<qint32> xTest (1,1,1);

return a.exec();
}

I obtain the error:


main.cpp:(.text+0x39): undefined reference to `MyLibraryClass<int>::MyLibraryClass(int, int, int)'

I'd like to know where's the error, and how can I compile successfully the executable.

Thanks in advance for your replies.

high_flyer
26th May 2011, 13:58
it looks like MyLibraryClass<T> does not have a constructor with the signature MyLibraryClass(T,T,T) , or that its header is not included.

jepessen
26th May 2011, 14:27
It's defined...

This is the declaration in my .h file


//! Constructor that defines only grid dimension
MyLibrary(qint32 qiX, qint32 qiY, qint32 qiZ);

This is the implementation in my .cpp file


template<class T>
MyLibrary<T>::MyLibrary(qint32 qiX, qint32 qiY, qint32 qiZ)
{

// Testing values to be greater or equal to zero.
if (qiX < 0)
{
qDebug() << "MyLibrary<T>::MyLibrary: qiX = " << " is less than zero."
<< " Setting X value to zero.";
m_qiX = 0;

}
else
{
m_qiX = qiX;
}

// etc etc etc...

}

high_flyer
26th May 2011, 14:48
You are mixing specialization and general template.
For specializazoin you need the following syntax:


template<>
MyLibrary::MyLibrary<quint32>(qint32 qiX, qint32 qiY, qint32 qiZ)
{...
}

Or a general template:


template<class T>
MyLibrary::MyLibrary(T qiX, T qiY, T qiZ)
{...
}


Ah and:

This is the implementation in my .cpp file

templates are implemented in headers, not in *.cpp files.
Or more correctly said:
The implementation (definition) of a template class or function must be in the same file as its declaration, and this is usually done in a header.
Read more abut how to create and use templates in c++.

jepessen
26th May 2011, 14:59
I don' use T for arguments of constructor. It defines the type of a private attribute of my class, that's used inside my constructor. qiX,Y,Z are indexes to access to a (T m_xGrid[][][]) structure inside my class.


template<class T>
MyLibrary<T>::MyLibrary(qint32 qiX, qint32 qiY, qint32 qiZ)
{

// Testing values to be greater or equal to zero.
if (qiX < 0)
{
qDebug() << "MyLibrary<T>::MyLibrary: qiX = " << " is less than zero."
<< " Setting X value to zero.";
m_qiX = 0;

}
else
{
m_qiX = qiX;
}

// etc etc etc...

// Example of use of T
T xValue;
xValue = m_xGrid[1][1][1];

}

high_flyer
26th May 2011, 15:20
It doesn't matter.
Your syntax is wrong and your implementation is in the wrong place.
Read well what I wrote, and google to some template tutorials.

jepessen
26th May 2011, 16:00
Ok, sorry... I'm reading something more about templates. Thanks for your reply.
Regards.

SixDegrees
27th May 2011, 08:50
Also, your application project file doesn't look right. 'LIBS += -L../../bin/libMyLibrary.so' just adds the directory to the linker search path; you need to add '-lMyLibrary' to it. The 'undefined reference' error indicates that the linker can't find your library.

But note that whatever else may be in your library, templated classes will not appear. Templates aren't code, and aren't compiled into libraries; templates are...templates that tell the compiler how to generate code when an actual instantiation of a template class occurs, so unless your library creates an instance of a template class there is nothing in it that's template related. The only place the template is defined is in the header, which is roped in at compile time.

This is all somewhat oversimplified.

jepessen
27th May 2011, 22:29
Thanks. Just to know, If I can't export a template with a library, how can works Qt container like, for example, QVector? Because in that case I simply include the qvector header and I can use the template. How can I do something similiar?

SixDegrees
27th May 2011, 22:43
You include all of your implementation in your header file so there's nothing to compile and nothing to build into a link library.

stampede
27th May 2011, 22:55
If I can't export a template with a library
You can deploy a header containing the template definition with other headers in library, I don't see a problem here.
Or do you mean you want to have a template code in .so file somehow ? In that case I'd suggest you read more about templates.
If this library is nothing more than a template, then you don't need any .so files, no linking to the library is required, because there is nothing to link to. All needed code will be generated in case of template instantiation.
So in fact using this library means including the header and creating an instance of template class (or method).

jepessen
27th May 2011, 23:15
Thanks, I've also read something about that. It's the first time that I use it for a serious project, so before I'd never noticed template differences from normal classes because I've used them always in the same project...

I have a lot to learn :-)

Thanks to anyone.