Undefined reference errors linking a dll in QtCreator - c++

I have built a simple dll using g++ under mingw:
We have an include file:
#ifndef __TESTDLL_H
#define __TESTDLL_H
class sineCalculator
{
double n;
public:
sineCalculator();
sineCalculator(double);
double sine();
void setAngle(double);
};
#endif
Then an implementation cpp:
#include <testdll.h>
#include <math.h>
sineCalculator::sineCalculator()
{
n = 0;
}
sineCalculator::sineCalculator(double x)
{
n = x;
}
double sineCalculator::sine()
{
return sin(n);
}
void sineCalculator::setAngle(double x)
{
n = x;
}
This I have compiled as a dll.producing both a .dll file and .a import library with the names visaTest.dll and libvisaTest.a
I can write a small program and link to this dll successfully just using the command line - no Qt just g++. I can create objects and run the methods all fine.
However, I now want to add this library to a Qt application within QtCreator. I have followed the advice of several questions and added these lines to my .pro file:
INCLUDEPATH += C:/msys64/home/hoyla/libs/
INCLUDEPATH +=C:/msys64/home/hoyla/includes/
DEPENDPATH +=C:/msys64/home/hoyla/libs/
win32:CONFIG(release, debug|release): LIBS += -LC:/msys64/home/hoyla/libs/ -lvisaTest
else:win32:CONFIG(debug, debug|release): LIBS += -LC:/msys64/home/hoyla/libs/ -lvisaTest
else:unix: LIBS += -L$$PWD/../../../../libs/ -lvisaTest
Although I use some absolute paths here I have also tried with relative paths. However, I keep getting undefined reference errors to my dll functions when building the Qt file. I would point out that the paths point to the location of my .a import library, the .dll itself is within the system path. What am I doing wrong here?

Mea Culpa! It seems I had compiled my library under 64-bit MinGW but Qt Creator was defaulting to the 32-bit toolchain. One would have thought that the linker might have been able to determine that was the error and generate a more useful error message but there we go. Lesson learned - make sure you're using the tools you think you're using.

Related

qmake - changes in configuration are not detected and the library doesn't recompile

I want to choose the files that are compiled into a static library based on a configuration.
To do that, I have created two configurations (A and B) in the QtCreator's Projects tab and in my .pro file I have
CONFIG(USE_A){
SOURCES += My_lib_a.cpp
}
CONFIG(USE_B){
SOURCES += My_lib_b.cpp
}
and it works, but there is a problem.
When I switch between A and B configurations a couple of times, after both of those versions have been built, qmake doesn't detect that there has been a change anymore and the library is stuck with the old file.
I'm forced to either touch the file that I want to recompile or manually choose to rebuild the library.
I've checked on Qt 5.12 and msvc 2017, but I need this to work on windows and linux.
Is this the correct way of doing this?
Is there a way to overcome this problem?
Minimal example:
// example/top.pro
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += \
my_lib\
app
// example/app/app.pro
TARGET = app
SOURCES += main.cpp
INCLUDEPATH += ../my_lib
DEPENDPATH += ../my_lib
LIBS += -L../my_lib/debug -lmy_lib
PRE_TARGETDEPS += ../my_lib/debug/my_lib.lib
// example/app/main.cpp
#include "My_lib.h"
int main()
{
My_lib m;
}
// example/my_lib/my_lib.pro
TARGET = my_lib
TEMPLATE = lib
CONFIG += staticlib
CONFIG(USE_A){
SOURCES += My_lib_a.cpp
}
CONFIG(USE_B){
SOURCES += My_lib_b.cpp
}
HEADERS += My_lib.h
// example/my_lib/My_lib.h
#pragma once
struct My_lib
{
My_lib();
};
// example/my_lib/My_lib_a
#include "My_lib.h"
#include <iostream>
My_lib::My_lib()
{
std::cout << "This is A" << std::endl;
}
// example/my_lib/My_lib_b
#include "My_lib.h"
#include <iostream>
My_lib::My_lib()
{
std::cout << "This is B" << std::endl;
}
Since you build the library in the same build directory, with the same target name, you'll always come out with the latest built file, whatever the current build configuration is set to.
To overcome the problem, you need to use separate build directories, one for each configuration.
In Build Settings, for each configuration, add %{CurrentBuild:Name} at the end of the Build directory path:
/somepath/example/%{CurrentBuild:Name}
Cleanup your current build directory, then build each configuration again. Given A and B your configuration names, you shold come out with a directory tree like this:
- somepath
- example
- A
+ app
+ my_lib
- B
+ app
+ my_lib

Library path is definitely correct and can create an instance of said library, but get "Undefined reference" when calling any function

I'm using Qt Creator to create a new project, and I have a test "MathLibrary" that I created in Visual Studio. I want to use this library in my Qt project.
I have searched for many hours for an answer to my solution and in almost all cases the answer was simply that the library had not been added to the PATH in the .pro file. I'm 99% sure that I have done everything correct, but something is causing me to get an Undefined Reference error when I try calling any function in this library. Here's what I have so far.
The library -
MathLibraryH.h:
#pragma once
namespace MathLibrary
{
class Functions
{
public:
// Returns a + b
double Add(double a, double b);
// Returns a * b
double Multiply(double a, double b);
// Returns a + (a * b)
double AddMultiply(double a, double b);
};
}
MathLibrary.cpp:
#include "stdafx.h"
#include "MathLibraryH.h"
namespace MathLibrary
{
double Functions::Add(double a, double b)
{
return a + b;
}
double Functions::Multiply(double a, double b)
{
return a * b;
}
double Functions::AddMultiply(double a, double b)
{
return a + (a * b);
}
}
The QT project -
TestQTProject.pro:
QT += core gui \
network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = TestQTProject
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp \
HEADERS += \
mainwindow.h \
FORMS += \
mainwindow.ui
DISTFILES += \
com_github_msorvig_s3.pri
LIBS += -L$$PWD/../Libs -lMathLibrary
INCLUDEPATH += $$PWD/../Incs
mainwindow.cpp:
#include "MathLibraryH.h"
// .... other stuff ....
void MainWindow::on_btnStage1_clicked()
{
MathLibrary::Functions lib; // This is just fine
lib.Add(5, 9); // The "Add" function (or any other function in the library)
causes an undefined reference error
}
I'm still new to Qt but I can't see what's wrong with any of this code.
Other things I've tried based on answers from searching:
Adding the following code to MathLibrary.h:
#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif
Changing the format of the LIBS declaration in the .pro file to all of the following:
Multi-line:
LIBS += -L$$PWD/../Libs
LIBS += -lMathLibrary
Hard coded single line:
LIBS += -LC:\svn\software\WIP\TestQTProject\Libs -lMathsLibrary
Nothing I've done works and I have no other ideas left.
For what it's worth, the library works fine in any project created using visual studio, and I've tried creating both a static and dynamic library.
Add
MATHLIBRARY_API
infront of your class name to export all public members in your dll. During export the dllexport part should be set and during import the dllimport part of course.
Here's a link that explains how to export classes from a dll:
https://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL
If you were trying to link dynamically, the problem is that your library MathsLibrary was not exported as a dynamic library, and neither you have imported it as a dynamic library (that's what __declspec(dllexport) does, and the macros should be used at the front of functions or classes declarations to make any difference). And even if you did, there is a chance that you have compiled it differently from your Qt application, so there is a linking issue.
But since you are trying to link statically (I didn't see any library file loading at your code), the problem seems to be the diff between the compilation of your library and your Qt application.
You should try to build your Qt Application with the same flags and same compiler that you built your library, or vice versa. If your code is working as you say, it maybe works.
For further details:
DL Library
How to Create a Plugin Framework
Building plugins using Qt Framework

How to embed SQLite into a C++ project

I'm trying to embed SQLite into my project. I have included the following files into a directory called lite : sqlite3.dll, sqlite3.h, and sqlite3.lib.
This is my project:
#include <stdio.h>
#include <lite/sqlite3.h>
int main(int argc, char* argv[])
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("test.db", &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return(0);
}else{
fprintf(stderr, "Opened database successfully\n");
}
sqlite3_close(db);
}
I get the following errors when I run the project:
:-1: error: cannot find -lsqlite3d
collect2.exe:-1: error: error: ld returned 1 exit status
What could I be doing wrong?
I'm working in Qt. This is my .pro file:
TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt
SOURCES += main.cpp
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lite/ -lsqlite3
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lite/ -lsqlite3d
else:unix: LIBS += -L$$PWD/lite/ -lsqlite3
INCLUDEPATH += $$PWD/lite
DEPENDPATH += $$PWD/lite
Since you are already using Qt why don't you use Qt SQL module? You are going to save a lot of pain, you will bypass this kind of linkage problems just by adding
QT += sql
to you Qt project file, and adding
#include <QtSql>
to you surce files. You'll have a lot of model-view classes that facilitate the integration of the database into your application UI.
This is the recommended way to use SQL in Qt applications, unless you have very very specific needs. You can have Qt use different SQL engines under the hood (SQLite, MySQL,...), but Qt will abstract all this for you.
Despite too late, there are a couple of issues here which I think were completely left out in this question, even though the workaround is practical ..
The error is quite clear .. linker could not find the "debug" version of the lib lsqlite3d which is so configured in qmake .pro file. either get the "debug" file of the lib, or remove this line from .pro
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lite/ -lsqlite3d
This seems a common mistake when adding a library in Qt .. there is an option like :
Add "d" suffix for debug version
And this must be deselected when there is no debug version of the lib.
Second and the essence of this answer, since SQLite is written in C , the include
section is not correct and wont work; It must be corrected to be:
extern "C" {
#include <lite/sqlite3.h>
}
With these two issues corrected .. there should be no problem adding SQLite library, or, in general, any C library to Qt.
Practically with small code like SQLite, another option is to statically compile it with the project .. by just adding sqqlite3.h and sqlite3.c to the Qt project and removing the linkage to sqlite3.lib in .pro .. with the include section as updated.

SYSTEMTIME in qt

I am a bit stuck at the moment with a little sample project that I would like to run to test some cryptology that I want to use in a main project.
Basically I am using the latest Qt Creator and I have created a simple window dialog. Furthermore, I would like to test the PBKDF2 implementation through CkCrypt2
So what I have done is downloading the X64 version of the library and added it to my project folder. I then told my Qt project to use an external library, the final .pro file looks like this:
#-------------------------------------------------
#
# Project created by QtCreator 2013-06-09T18:09:44
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = crypt2test
TEMPLATE = app
SOURCES += main.cpp\
m
ainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/libs/ -lChilkatDbgDll_x64
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/libs/ -lChilkatDbgDll_x64d
else:unix: LIBS += -L$$PWD/libs/ -lChilkatDbgDll_x64
INCLUDEPATH += $$PWD/include
DEPENDPATH += $$PWD/include
I can successfully load the library but I cannot start the application.
My mainwindow.cpp looks like this:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "CkCrypt2.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
CkCrypt2 crypt;
bool success;
success = crypt.UnlockComponent("Just some random text ");
if ( !success )
{
qDebug() << "Not successfully unlocking the library";
}
}
MainWindow::~MainWindow()
{
delete ui;
}
The error message I get in the compiler is:
c:\qt\qt5.0.2\tools\qtcreator\bin\crypt2test\include\CkString.h:127: error: C2061: syntax error : identifier 'SYSTEMTIME'
c:\qt\qt5.0.2\tools\qtcreator\bin\crypt2test\include\CkString.h:129: error: C2061: syntax error : identifier 'SYSTEMTIME'
C:\Qt\Qt5.0.2\Tools\QtCreator\bin\crypt2test\include\CkCrypt2.h:429: error: C2061: syntax error : identifier 'SYSTEMTIME'
Looking into the files I see:
void appendDateRfc822(SYSTEMTIME &sysTime);
void appendDateRfc822Gmt(SYSTEMTIME &sysTime);
// GETSIGNATURESIGNINGTIME_BEGIN
bool GetSignatureSigningTime(int index, SYSTEMTIME &outSysTime);
// GETSIGNATURESIGNINGTIME_END
Okay, so it is complaining about the SYSTEMTIME construct. So I look up the error C2061
Basically it says:
The compiler found an identifier where it wasn't expected. Make sure
that identifier is declared before you use it.
Which makes sense, so I look up the SYSTEMTIME and try to do :
#include <windows.h>
But that leads to many more errors in the windows.h file itself.
I use the MS Visual C++ compiler in Qt. Even though I use qmake. I am very new to this and I do not understand it all yet. Furthermore, I have no idea how to fix this, because including the windows.h does not help.
What seems to be the problem here ? Is this an issue regarding my compiler or the constulation that I use a third party app which library is compiled with MS Visual C++ and I am now trying to use this on my Windows machine in Qt with a Windows Visual C++ compiler ?
For any help I am gratefully thankful!
EDIT1:
Actually, after a clean all and qmake and build project I have now different errors and none were found in the Windows.h as previously stated. Since there were so many I have made a screenshot: http://i.imgur.com/B8EoENB.png
EDIT2:
I have adjusted the library that I include. Before this I was using the multi-threaded library of CkCrypt in the Debug mode. I have now included the single realease library. Which is located in the same directory.
When including windows.h I got the errors that things were already defined. So I removed the line again. With this result: http://i.imgur.com/z415txR.png
This shows at the bottom that MSVCRT conflichts with other library. It mentions to use NODEFAULTLIB:library but I am not to sure how to do that. Will google and keep this up to date as I process.
Many years ago, Chilkat was originally developed for the Windows platform only, and used SYSTEMTIME for this reason. In the last 5 years (approx) Chilkat is cross-platform, and SYSTEMTIME no longer makes sense. To cope with the issue, there is a "SystemTime.h" header in the same directory as the CkCrypt2.h header file. You could include this to solve the problem. (However, if WIN32 is defined, you'll probably need to edit SystemTime.h to remove the #ifdef.)
In any case, the methods using SYSTEMTIME are going to be deprecated. For any method or property that uses SYSTEMTIME, there should be a newer alternative method/property that instead uses CkDateTime.
Finally, Chilkat will test with Qt so that for the next version, (hopefully) Qt out-of-the-box will compile without any pitfalls.

Using External Lib/DLLs in Qt Creator?

I decided after a bunch of headaches all morning, that using Qt Creator for my first Qt project would probably be better than MSVC (had too many issues compiling).
I am wondering though how I can add the .dlls and .libs I need for my external tools through Qt Creator. I found this post Adding external library into Qt Creator project which makes sense.
I need a little more info though such as...Do I link dlls or libs first, what is the syntax to add dlls to the build step in qmake (i assume its close to win32:LIBS += path/to/Psapi.lib)
Thanks!
Compiling external libraries with QtCreator/gcc
If you own the source code of your libraries this is the .pro file to make an external library (.dll and .a) or Framework (on Mac OS X) from them:
TEMPLATE = lib
INCLUDEPATH = <your-include-paths>
HEADERS += <your-headers>
SOURCES += <your-sources>
TARGET = MyLib /* The name of your libary */
/* Win32: To generate a MyLib.dll and libMyLib.a (gcc) or MyLib.lib (MSVC) file */
win32 {
CONFIG += dll
}
/* Just in case you need to generate Mac Frameworks: */
macx {
CONFIG += shared lib_bundle
FRAMEWORK_HEADERS.version = Versions
FRAMEWORK_HEADERS.files += <your library headers>
/* Example:
FRAMEWORK_HEADERS.files += /path/to/your/lib/MyLib.h
*/
FRAMEWORK_HEADERS.path = Headers
QMAKE_BUNDLE_DATA = FRAMEWORK_HEADERS
VERSION = 0.5.0 // a framework version you can define
}
Adding external libraries to your QtCreator/gcc project
/* your project settings */
/* If you compile on windows */
win32 {
/* If you compile with QtCreator/gcc: */
win32-g++:LIBS += /path/to/your/libMyLib.a
/* IF you compile with MSVC: */
win32-msvc:LIBS += /path/to/your/libMyLib.lib
}
/* If compile on Mac and want to link against a framework */
macx {
LIBS+= -framework MyLib
QMAKE_FLAGS += -F/path/to/MyLib
}
Note that to use external libraries with gcc you need the libMyLib.a file that contains the linking information. The libMyLib.lib are generated by MS Visual Studio and can't be processed by gcc afaik!