Creating Custom QT Library - c++

I created a static Qt library by using VS2005.
It created an extra file "test_global.h" besides expected ones(test.h and test.cpp).
test_global.h
#ifndef TEST_GLOBAL_H
#define TEST_GLOBAL_H
#include <Qt/qglobal.h>
#ifdef TEST_LIB
# define TEST_EXPORT Q_DECL_EXPORT
#else
# define TEST_EXPORT Q_DECL_IMPORT
#endif
#endif // TEST_GLOBAL_H
Why this file is generated, how I suppose to use it?
Thanks.

You mark your class (or methods) as exported in your library headers:
class TEST_EXPORT TestClass {
// ...
};
Then in your library pro file you add:
DEFINES += TEST_LIB
So during the dll compilation your class header will have "Q_DECL_EXPORT" macro which is Qt way to tell the linker "export this class/method", and when you use your dll in some application, the header will have "Q_DECL_IMPORT" macro.
For more information, check the Qt documentation.

Related

how to import project header files from another project and use it as library for qtcreator projects

I have two projects in qtcreator: BiosPatcher - the code & BiosPatcherTest - googletest unit tests for BiosPatcher code. Advice from here:
multiple main declaration in qtcreator project which uses googletest
How to import sources from one project in another and connect builded project as library in qtcreator to another qtcreator project?
BiosPatcher project has:
BiosPatcher\src\bios\Bios.{cpp, hpp} class
and in BiosPatcherTest i have test:
#include "src/bios/Bios.hpp" //not works
...
TEST(BiosTest, testReadMethodReadsFromBiosIO) {
MockBiosIO mockBiosIO;
EXPECT_CALL(mockBiosIO, readAsBytes())
.Times(AtLeast(1));
MockReentrantLock mockReentrantLock;
MockBiosVector mockBiosVector;
MockPatch mockPatch;
MockLog mockLog;
Bios bios;
bios.setBiosIO(&mockBiosIO);
bios.setLock(&mockReentrantLock);
bios.setBiosBytesVector(&mockBiosVector);
bios.setLog(&mockLog);
bios.setPatch(&mockPatch);
bios.read();
}
First, you need create BiosPatcher C++ shared library project.
After, you need just add BIOSPATCHER_LIBRARY to class declaration
this
class BiosPatcher
{
need to be replaced by this
class BIOSPATCHERSHARED_EXPORT BiosPatcher
{
and after it just compile your library and include same headers in your second project, and add to linking generated .lib file.
DEPENDPATH''= . ../BiosPatcher
INCLUDEPATH ''= ../BiosPatcher
LIBS''= -L../BiosPatcher/debug -lBiosPatcher
When I created library project in my Qt Creator with name BiosPatcher, IDE automaticly created biospatcher_global.h file, that containts BIOSPATCHERSHARED_EXPORT defination. That file need to be included in all library headers.
You see, if defined BIOSPATCHER_LIBRARY then BIOSPATCHERSHARED_EXPORT will be defined as Q_DECL_EXPORT, else Q_DECL_IMPORT. BIOSPATCHER_LIBRARY is defined in library .pro file, that means if you include those headers from another project, class will be imported from compiled library.
#ifndef BIOSPATCHER_GLOBAL_H
#define BIOSPATCHER_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(BIOSPATCHER_LIBRARY)
# define BIOSPATCHERSHARED_EXPORT Q_DECL_EXPORT
#else
# define BIOSPATCHERSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // BIOSPATCHER_GLOBAL_H
Also read this: https://wiki.qt.io/How_to_create_a_library_with_Qt_and_use_it_in_an_application

How to declare a class shared between a library and an application

I have a common utility class that is shared between two projects, an desktop application project and a library project (dll). I'm working under VS2013.
To make this class available to external calls when it's compiled as part of my library, I use a macro like this:
#include "global.h"
class MYCLASS_EXPORT UtilityClass {
public:
...
My global.h file contains the following:
#ifdef MYCLASS_LIBRARY
# define MYCLASS_EXPORT __declspec(dllexport)
#else
# define MYCLASS_EXPORT __declspec(dllimport)
#endif
So when I use that class inside my library I set the preprocessor macro MYCLASS_LIBRARY and an application that link my library can use the UtilityClass.
Instead, when I use that class as part of my C++ desktop application project (that doesn't have the preprocessor macro MYCLASS_LIBRARY), I get from the compiler an "inconsistent dll linkage" error because of MYCLASS_EXPORT declaration.
So, how to declare my class so that can be used both in a library project and in a desktop application project (so without the need to export that class)?
Just to be more clear, a working solution I've found is the following:
#ifdef MYCLASS_LIBRARY
#include "global.h"
#endif
#ifdef MYCLASS_LIBRARY
class MYCLASS_EXPORT UtilityClass {
#else
class UtilityClass {
#endif
public:
...
Now everything compile and run fine, but does not seem a good approach...
I can think of the following option:
In the desktop application, define a macro, MYCLASS_STATIC and change the .h file to use:
#ifdef MYCLASS_STATIC
# define MYCLASS_EXPORT
#elif defined(MYCLASS_LIBRARY)
# define MYCLASS_EXPORT __declspec(dllexport)
#else
# define MYCLASS_EXPORT __declspec(dllimport)
#endif

Calling function from dll with QT

I created by the first time a dll to use with C++ (and then C#, I have plans to share this dll between a C++ and C# applications) using QT creator but when I try to use it I get SEGFAULT error.
Here's my files:
mydll.h
#ifndef MYDLL_H
#define MYDLL_H
#include "mydll_global.h"
class MYDLLSHARED_EXPORT MyDll
{
public:
MyDll();
int getAnswer();
};
MYDLLSHARED_EXPORT int getNumber();
#endif // MYDLL_H
mydll_global.h
#ifndef MYDLL_GLOBAL_H
#define MYDLL_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(MYDLL_LIBRARY)
# define MYDLLSHARED_EXPORT Q_DECL_EXPORT
#else
# define MYDLLSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // MYDLL_GLOBAL_H
mydll.cpp
#include "mydll.h"
MyDll::MyDll()
{
}
int MyDll::getAnswer()
{
return 42;
}
int getNumber()
{
return 10;
}
So I build it and created mydll.dll: then I went to other C++ project wheere I want to use this dll and put in the .pro file:
LIBS += "C:\path\to\mydll.h"
and in the main.cpp
#include "mydll.h"
and when I use function from dll like this:
qDebug() << getNumber();
I get a SEGFAULT error.
I thought that the header to provide the compiler type information and the dll to compiler to provide the function body was all I needed but as I'm getting a SEGFAULT I'm acessing NULL or someone else memory or so (I can't see the value on debug).
What am I missing?
First off, to link the DLL you need the link .lib file for that DLL. That file has all the binary manifest for linking.
Second, project file LIBS clause specify the list of .lib files to link with. Some of them may represent dynamic libraries (.dll).
See the example: Linking to Shared Library in Qt
Even better article covering both creation of DLL with Qt and using DLL in your Qt project: https://wiki.qt.io/How_to_create_a_library_with_Qt_and_use_it_in_an_application
I had this same issue. Almost every example I looked at had a class as their example, but I wanted to export functions like getNumber(). It's in the qt5 docs as you probably know by now.
This line needs to be in your header file:
extern "C" MYDLLSHARED_EXPORT int getNumber();
and it is either the mydll_global.h or mydll.h depending on what you are using.
mydll_global.h would be what qtcreator creates and puts export definitions in if you create a new Shared Library project.
I was thrown off guard by the extern "C" part as I wasn't using C and wasn't as familiar with how compilers export symbols.
Trying to add a public static function to a class definition using static MYDLLSHARED_EXPORT int getNumber(); or simply using a namespace (function defined with or without static) will give a not found for architecture x86_64 error using clang on osx.

C++ parameterized header inclusion

I'm working on an image processing project, and have created many libraries for different feature extraction methods. I have also another library that uses one of these libraries.
I don't want to include all of them, so I would like to selectively include libraries based on parameters defined by a config file. The config file stores the parameter and its value as shown below:
lib: "a"
Is it possible to selectively include "library a" by reading the parameters in from this config file?
You can include conditionals in compilation time with #ifdef #ifndef #endif directives
#define TypeA
#define TypeB
#ifdef TypeA
#include <lib.h>
#endif
#ifdef TypeB
#include <stdio.h>
#endif

Compile dll in Qt with VS compiler to use it in Borland

I have a package of C functions and I need to create DLL library from it, that can be used in C++ program. I haven't done any library before, so I am total beginner in that. I am working in Qt Creator.
My first try was to create it according to the manual Creating shared libraries, so I added these two lines to my project file:
TEMPLATE = lib
DEFINES += MYLIB_LIBRARY
Then I created mylib.h file
#ifndef MYLIB_H
#define MYLIB_H
#include "mylib_global.h"
#include "functions1.h"
#include "functions2.h"
#include "functions3.h"
class MYLIBSHARED_EXPORT Mylib
{
public:
Mylib(){};
};
#endif // MYLIB_H
Finally I added mylib_global.h:
#ifndef MYLIB_GLOBAL_H
#define MYLIB_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(MYLIB_LIBRARY)
# define MYLIBSHARED_EXPORT Q_DECL_EXPORT
#else
# define MYLIBSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // MYLIB_GLOBAL_H
To make functions usable in C++ I used these lines for each function in library
#ifdef __cplusplus
extern "C"{
#endif
void foo();
#ifdef __cplusplus
}
#endif
When compiling with MSVC2012 everything seems ok and I got some .dll file. But then I sent library to someone, who wanted to use it in Borland C++. He told me that I have to compile it with some DEF file to tell to VS compiler right names and with __stdcall instead of __cdecl. But I have no idea how to do it in Qt. Any explanation and help would be really appreciated. Thanks
P.S. I looked at posts Using VS dll in old Borland and Import VS dll in C Builder, but they
did not help me to understand the problem.
If you want to export the foo function, you need to tell the linker somehow.
What you were suggested is to use a .def file, which is quite easy.
Just create a file like exports.def in your project directory, and write in it something like:
EXPORTS
foo
Then go to your library project settings -> Linker -> Input -> Module Definition File
and fill in your .def file name