I have been trying to use OpenCV in my Qt-based application. However, I am running into linking errors for some reason.
I am using Qt 5.5.0, MSVC 12.0, OpenCV 3.0, Windows 7. My OpenCV is unpacked in C:\opencv folder. I am not trying to compile the library myself, just using what came in the package. As shown in the code below, I am linking to libraries located in vc12 folder.
I have removed all my code and made it really basic for troubleshooting purposes, so I have a default starter QtWidget project (with an empty screen), to which I added a single line:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <opencv2/core.hpp>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
cv::Mat M;
}
MainWindow::~MainWindow()
{
delete ui;
}
If I comment out the only openCV command (cv::Mat M;) the code compiles and runs. With this line present I am getting two unresolved symbol errors:
mainwindow.obj:-1: error: LNK2019: unresolved external symbol "void __cdecl cv::fastFree(void *)" (?fastFree#cv##YAXPEAX#Z) referenced in function "public: __cdecl cv::Mat::~Mat(void)" (??1Mat#cv##QEAA#XZ)
mainwindow.obj:-1: error: LNK2019: unresolved external symbol "public: void __cdecl cv::Mat::deallocate(void)" (?deallocate#Mat#cv##QEAAXXZ) referenced in function "public: void __cdecl cv::Mat::release(void)" (?release#Mat#cv##QEAAXXZ)
I have tried various ways to statically link openCV libraries, but I keep getting the same errors (I always clean, re-run QMake, and then re-build the project for every attempt). Here is what my .pro file looks like right now (I ended up adding all static libs hoping that would help - it did not):
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = Test
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
win32:CONFIG(release, debug|release): LIBS += -LC:/opencv/build/x86/vc12/staticlib \
-lopencv_core300 \
-lopencv_highgui300 \
-lopencv_imgproc300 \
-lIlmImf \
-lippicvmt \
-llibjasper \
-llibjpeg \
-llibpng \
-llibtiff \
-llibwebp \
-lopencv_calib3d300 \
-lopencv_features2d300 \
-lopencv_flann300 \
-lopencv_hal300 \
-lopencv_imgcodecs300 \
-lopencv_ml300 \
-lopencv_objdetect300 \
-lopencv_photo300 \
-lopencv_shape300 \
-lopencv_stitching300 \
-lopencv_superres300 \
-lopencv_ts300 \
-lopencv_video300 \
-lopencv_videoio300 \
-lopencv_videostab300 \
-lzlib
else:win32:CONFIG(debug, debug|release): LIBS += -LC:/opencv/build/x86/vc12/staticlib \
-lopencv_core300d \
-lopencv_highgui300d \
-lopencv_imgproc300d \
-lIlmImfd \
-lippicvmt \
-llibjasperd \
-llibjpegd \
-llibpngd \
-llibtiffd \
-llibwebpd \
-lopencv_calib3d300d \
-lopencv_features2d300d \
-lopencv_flann300d \
-lopencv_hal300d \
-lopencv_imgcodecs300d \
-lopencv_ml300d \
-lopencv_objdetect300d \
-lopencv_photo300d \
-lopencv_shape300d \
-lopencv_stitching300d \
-lopencv_superres300d \
-lopencv_ts300d \
-lopencv_video300d \
-lopencv_videoio300d \
-lopencv_videostab300d \
-lzlibd
INCLUDEPATH += C:/opencv/build/include/
DEPENDPATH += C:/opencv/build/include/
Is there something in particular I am missing about the configuration? I am pretty sure the basic syntax (like slashes, etc) is ok since I was able to link another library in Qt Creator in another project, but I will be more than happy to try any suggestions at this point.
So after searching around and multiple attempts I found out what was wrong. I was linking to x86 library instead of x64. If I changed to x64 libs, I was getting mismatch between Static and Dynamic linker directives. Linking OpenCV statically would not work since OpenCV libraries themselves link to libcmt.lib, whereas Qt (pre-built) links dynamically to the counter-part of libcmt.lib, i.e. to msvcrt.lib. And since these two MS libraries are one and the same (just one is for static linking, the other for dynamic), I had two options: either rebuild Qt or OpenCV (which I don't want to do - I am very new to this kind of issues), or link OpenCV dynamically.
I opted for the second option. All you have to do is to remove all references to /staticlib folder and libs that it contains, and replace it with the following:
win32:CONFIG(release, debug|release): LIBS += -LC:/opencv/build/x64/vc12/lib -lopencv_world300
else:win32:CONFIG(debug, debug|release): LIBS += -LC:/opencv/build/x64/vc12/lib -lopencv_world300d
Note that one has to distribute corresponding DLLs with the application (located in build\x64\vc12\bin\ folder).
Related
I want to use Graphviz in my Qt application, but I haven't used any third-party libraries before. I've found the following video on YouTube which shows how to use third-party DLLs in Qt. I've downloaded Graphviz 2.38 and copied all headers to my program folder as in the video, and copied all dlls to debug and release builds, and added these dlls as libraries in .pro file. But I still get "undefined reference" errors to functions from graphviz libraries. So does the method shown in the video still work in Qt6 ? Or did I do something wrong ?
.pro file:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
arith.h \
cdt.h \
cgraph.h \
color.h \
geom.h \
graph.h \
gvc.h \
gvcext.h \
gvcjob.h \
gvcommon.h \
gvconfig.h \
gvplugin.h \
gvplugin_device.h \
gvplugin_layout.h \
gvplugin_loadimage.h \
gvplugin_render.h \
gvplugin_textlayout.h \
gvpr.h \
mainwindow.h \
pack.h \
pathgeom.h \
pathplan.h \
textpara.h \
textspan.h \
types.h \
usershape.h \
xdot.h
LIBS += "C:\...\build-BSP_Emulator_alpha-Desktop_Qt_6_2_0_MinGW_64_bit-Debug\debug\ann.dll"
LIBS += "C:\...\build-BSP_Emulator_alpha-Desktop_Qt_6_2_0_MinGW_64_bit-Debug\debug\cdt.dll"
LIBS += "C:\...\build-BSP_Emulator_alpha-Desktop_Qt_6_2_0_MinGW_64_bit-Debug\debug\cgraph.dll"
LIBS += "C:\...\build-BSP_Emulator_alpha-Desktop_Qt_6_2_0_MinGW_64_bit-Debug\debug\gvc.dll"
LIBS += "C:\...\build-BSP_Emulator_alpha-Desktop_Qt_6_2_0_MinGW_64_bit-Debug\debug\gvplugin_core.dll"
LIBS += "C:\...\build-BSP_Emulator_alpha-Desktop_Qt_6_2_0_MinGW_64_bit-Debug\debug\gvplugin_dot_layout.dll"
LIBS += "C:\...\build-BSP_Emulator_alpha-Desktop_Qt_6_2_0_MinGW_64_bit-Debug\debug\gvplugin_gd.dll"
LIBS += "C:\...\build-BSP_Emulator_alpha-Desktop_Qt_6_2_0_MinGW_64_bit-Debug\debug\gvplugin_gdiplus.dll"
LIBS += "C:\...\build-BSP_Emulator_alpha-Desktop_Qt_6_2_0_MinGW_64_bit-Debug\debug\gvplugin_neato_layout.dll"
LIBS += "C:\...\build-BSP_Emulator_alpha-Desktop_Qt_6_2_0_MinGW_64_bit-Debug\debug\gvplugin_pango.dll"
LIBS += "C:\...\build-BSP_Emulator_alpha-Desktop_Qt_6_2_0_MinGW_64_bit-Debug\debug\Pathplan.dll"
LIBS += "C:\...\build-BSP_Emulator_alpha-Desktop_Qt_6_2_0_MinGW_64_bit-Debug\debug\vmalloc.dll"
FORMS +=
main.cpp:
#include "mainwindow.h"
#include "gvc.h"
#include <QApplication>
int main(int argc, char *argv[])
{
//QApplication a(argc, argv);
MainWindow main_window;
main_window.setGeometry(100,100,1000,1300);
main_window.show();
GVC_t *gvc;
Agraph_t *g;
FILE *fp;
gvc = gvContext();
if (argc > 1)
fp = fopen(argv[1], "r");
else
fp = stdin;
g = agread(fp, 0);
gvLayout(gvc, g, "dot");
gvRender(gvc, g, "plain", stdout);
gvFreeLayout(gvc, g);
agclose(g);
return (gvFreeContext(gvc));
}
In the 'LIBS +=' section you must set not the *.dll files, but rather .lib(on windows) or (lib.a) on unix
When you download library you probably have files like:
library.dll - file with compiled code used only by operating system
library.lib (win32) - file used by linker to connect you program with library
Dll isn't need to compile program at all, it's used only when system startups your program.
currently working on a Qt project and I'd also like to use some aspects of the Poco libraries such as the property file configuration functionality. I got the example in my code from page nine of the documentation here:
http://pocoproject.org/slides/180-Configuration.pdf
The problem is when compiling, a couple of rather oddly formatted undefined reference errors appear.
C:\projects\build-InternetofGauges-Desktop_Qt_5_5_1_MinGW_32bit-Debug\debug\webtunnelhandler.o:-1: In function `ZN16WebTunnelHandler13setConfigFileEv':
C:\projects\InternetofGauges\webtunnelhandler.cpp:41: error: undefined reference to `_imp___ZN4Poco4Util25PropertyFileConfigurationC1ERKSs'
C:\projects\InternetofGauges\webtunnelhandler.cpp:43: error: undefined reference to `_imp___ZNK4Poco4Util21AbstractConfiguration6getIntERKSs'
C:\projects\build-InternetofGauges-Desktop_Qt_5_5_1_MinGW_32bit-Debug\debug\webtunnelhandler.o:-1: In function `ZN4Poco7AutoPtrINS_4Util25PropertyFileConfigurationEEptEv':
C:\My-Devices-SDK\include\Poco\AutoPtr.h:190: error: undefined reference to `_imp___ZN4Poco20NullPointerExceptionC1Ei'
C:\My-Devices-SDK\include\Poco\AutoPtr.h:190: error: undefined reference to `_imp___ZN4Poco20NullPointerExceptionD1Ev'
collect2.exe:-1: error: error: ld returned 1 exit status
My .pro file
QT += core
QT += network
QT += sql
QT += xml
QT -= gui
CONFIG += c++11
TARGET = InternetofGauges
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
INCLUDEPATH += "C:\\My-Devices-SDK\\include" \
"C:\\OpenSSL\\MinGW\\include"
LIBS += -L"C:\\My-Devices-SDK\\lib\\" \
-lPocoUtild \
-lPocoNetd \
-lPocoNetSSLd \
-lPocoFoundationd \
-lPocoJSONd \
-lPocoWebTunneld \
-lPocoXMLd
LIBS += -L"C:\\My-Devices-SDK\\lib\\" \
-lPocoUtil \
-lPocoNet \
-lPocoNetSSL \
-lPocoFoundation \
-lPocoJSON \
-lPocoWebTunnel \
-lPocoXML
LIBS += -L"C:/OpenSSL/MinGW/lib/"
SOURCES += main.cpp \
webclient.cpp \
startuphandler.cpp \
webtunnelhandler.cpp
DISTFILES += \
Todo.readme
HEADERS += \
webclient.h \
startuphandler.h \
webtunnelhandler.h
The problem code in question
#include <Poco/Util/PropertyFileConfiguration.h>
#include <Poco/AutoPtr.h>
#include "webtunnelhandler.h"
using Poco::AutoPtr;
using Poco::Util::PropertyFileConfiguration;
/* ... */
void WebTunnelHandler::setConfigFile()
{
AutoPtr<PropertyFileConfiguration> pConf;
pConf = new PropertyFileConfiguration("WebTunnelAgent.properties");//Error appears here
int key1 = pConf->getInt("webtunnel.httpPort");//and also here
return;
}
Now, I've compiled all the poco libraries with MinGW and Qt is also configured for MinGW and compiles and runs great with other parts of my program. I'm also happily using Qt 5.5.1 with the 3.1.6 Qt Creator. My happiness with Qt unfortunately doesn't help my issues.
I have looked at many a stack overflow question on similar topics, and have attempted to recompile the libraries as well as explicitely include the libraries in the .pro file. I also peeked into the Auto.h file and found that it ends up calling the null pointer exception likely due to the line pConf = new PropertyFileConfiguration("WebTunnelAgent.properties"); getting angry at me.
What are the causes of this error? And how does one fix this error?
Linking order of libraries matters and that has nothing to do with Poco:
the linker searches and processes libraries and object files in the
order they are specified. Thus, 'foo.o -lz bar.o' searches library
'z' after file foo.o but before bar.o. If bar.o refers to functions
in 'z', those functions may not be loaded.
Okay so I did manage to fix it. I realized that the order of libraries does in fact matter as there are some dependencies between libraries in this case. I also had to add another windows specific library to make it work. Here's the section of the .pro file that worked
LIBS += -L"C:\\My-Devices-SDK\\lib\\" \
-lPocoUtild \
-lPocoNetd \
-lPocoNetSSLd \
-lPocoXMLd \
-lPocoJSONd \
-lPocoWebTunneld \
-lPocoFoundationd
LIBS += -L"C:\\My-Devices-SDK\\lib\\" \
-lPocoUtil \
-lPocoNet \
-lPocoNetSSL \
-lPocoXML \
-lPocoJSON \
-lPocoWebTunnel \
-lPocoFoundation
LIBS += -L"C:/OpenSSL/MinGW/lib/"
win32:LIBS += -lIphlpapi
As I said above, Iphlpapi is needed as well as that poco order. Hope this helps someone eventually!
I am trying to add two different external library path on Qt. So I put INCLUDEPATH and LIBS below to .pro file;
INCLUDEPATH += C:/SiliconSoftware/Runtime5.4.0/include \
C:/Basler/pylon4/pylon/include
LIBS += -L"C:\SiliconSoftware\Runtime5.4.0\lib\visualc" \
-lclsersis \
-ldisplay_lib \
-lfglib5 \
-lgbelib \
-liolibrt \
-lsiso_auxport \
-lsiso_genicam
LIBS += -L"C:\Basler\pylon4\pylon\lib\Win32" \
-lPylonUsb_MD_VC100_TL \
-lPylonUtility_MD_VC100 \
-lPylon1394_MD_VC100_TL \
-lPylonBase_MD_VC100 \
-lPylonBootstrapper \
-lPylonCLSer_MD_VC100_TL \
-lPylonGigE_MD_VC100_TL \
-lPylonGUI_MD_VC100
But I got this error;
C:\Users\GitekVision\Documents\Qt Projects\PylonSetUp\pylonsetup.h:4: error: >C1083: Cannot open include file: 'pylon/PylonIncludes.h': No such file or >directory.
I tried to take libraries one by one, it works. But together not working.
Anyone knows how to use 2 different external library on Qt project?
I just built the static libraries from Qt 5.3.1 for Windows x86 with MSVC 2013. The second step is obviously a static linked application that uses these libraries. So I created a small application (just a MainWindow with some controls, for testing purposes). This is my *.pro-file:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = projectname
TEMPLATE = app
CONFIG += static
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
LIBS += -LC:\statics\lib\ -lQt5Core \
-LC:\statics\lib\ -lQt5Gui \
-LC:\statics\lib\ -lQt5Widgets \
-LC:\statics\lib\ -lqtmain \
-LC:\statics\lib\ -lQt5PlatformSupport \
INCLUDEPATH += C:\statics\include
Yeah. This is what I got from several tutorials/my memory from when I worked with 5.1. But when compiling I get those errors:
Qt5Core.lib(Qt5Core.dll):-1: error: LNK2005: "public: __thiscall QString::~QString(void)" (??1QString##QAE#XZ) allready defined in mainwindow.obj.
mainwindow.obj:-1: error: LNK2019: Unresolved extern symbol ""public: static struct QArrayData const * const QArrayData::shared_null" (?shared_null#QArrayData##2QBU1#B)" in Funktion ""public: __thiscall QString::QString(void)" (??0QString##QAE#XZ)".
moc_mainwindow.obj:-1: error: LNK2001: Unresolved extern symbol ""public: static struct QMetaObject const QMainWindow::staticMetaObject" (?staticMetaObject#QMainWindow##2UQMetaObject##B)".
Does somebody know how to handle these errors? Do I have to link against some other libraries not mentioned above, or include some files? I googled this topic and found out that many people experienced the same problem, but they mostly use older versions of Qt oder VS. I also tried to export the project to Visual Studio (working from Qt Creator), but the errors remain.
Thank you for your answers :)
QT += core gui
LIBS += -LC:\statics\lib\ -lQt5Core \
-LC:\statics\lib\ -lQt5Gui \
You are loading both Qt libraries twice: default and custom versions. By default, QT contains both core and gui libraries... you must delete them manually:
QT -= core gui
Just remove LIBS, INCLUDEPATH from project file and run qmake from static build on the project file to create makefile. If this will not help check your PATH
I have a game with two separate projects for the application itself and the tests. I'm building all of the projects in-source. Here's a shortened version of my project structure:
game
game.pro
app
app.pro
Entity.h
Entity.cpp
Entity.o
moc_Entity.cpp
moc_Entity.o
tests
layer
layer.pro
Entity.o (duplicated)
moc_Entity.cpp (duplicated)
moc_Entity.o (duplicated)
tst_Layer.cpp
app.pro:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4) {
QT += widgets
}
TARGET = cotw-clone
TEMPLATE = app
MOC_DIR = .moc
OBJECTS_DIR = .obj
HEADERS += MainWindow.h \
Map.h \
Tile.h \
Character.h \
Layer.h \
NewGameDialog.h \
GameController.h \
Stair.h \
Random.h \
MapGenerator.h \
TileData.h \
Statistics.h \
StatisticsDialog.h \
StatisticWidget.h \
Range.h \
Level.h \
RandomMapGenerator.h \
AiController.h \
MonsterJournalWidget.h \
InventoryDialog.h \
PathSearch.h \
PathNode.h \
Path.h \
Geometry.h \
EntityDatabase.h \
EntityData.h \
Entity.h \
CharacterData.h \
EntityMetadata.h
SOURCES +=\
MainWindow.cpp \
Map.cpp \
Tile.cpp \
Character.cpp \
Layer.cpp \
NewGameDialog.cpp \
GameController.cpp \
Stair.cpp \
TileData.cpp \
Statistics.cpp \
StatisticsDialog.cpp \
StatisticWidget.cpp \
Level.cpp \
RandomMapGenerator.cpp \
AiController.cpp \
MonsterJournalWidget.cpp \
InventoryDialog.cpp \
PathSearch.cpp \
PathNode.cpp \
Path.cpp \
EntityDatabase.cpp \
EntityData.cpp \
Entity.cpp \
CharacterData.cpp \
main.cpp
FORMS += MainWindow.ui \
NewGameDialog.ui \
StatisticsDialog.ui \
StatisticWidget.ui \
MonsterJournalWidget.ui \
InventoryDialog.ui
RESOURCES += \
icons/icons.qrc \
tiles/tiles.qrc
RESOURCES += \
entities/entities.qrc
My problem is that all of the tests projects use classes from the app project, which means they're compiling all of these classes even though they've already been compiled when app was built. Take the layer test project, for example:
layer.pro:
QT += testlib
QT -= gui
greaterThan(QT_MAJOR_VERSION, 4) {
QT += widgets
}
TARGET = tst_LayerTest
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += tst_LayerTest.cpp
DEFINES += SRCDIR=\\\"$$PWD/\\\"
HEADERS += "../../app/Entity.h"
SOURCES += "../../app/Entity.cpp"
So how can I point qmake to the .o (and qrc_, .moc etc.) files that have already been produced in app? Is there some qmake variable for this purpose, or is my project structure just fundamentally flawed?
You can use wildcards in qmake .pro files, to save having to maintain a list of all file names.
For example,
SOURCES += *.cpp
Each time you run qmake, that pattern *.cpp gets expanded in to the current list of files matching the pattern.
You can also use -= to remove file names, if you have a particular filename that you wish to exclude.
For example:
SOURCES += *.cpp
SOURCES -= main.cpp
Edit
I almost suggested in my earlier answer that you introduce a library, using qt's lib template, to contain your common code.
Then your build structure would look like this - assuming that you can move files around, from app/ to lib/:
game
game.pro
app
app.pro
main.cpp
lib
lib.pro
Entity.h
Entity.cpp
Entity.o
moc_Entity.cpp
moc_Entity.o
tests
layer
layer.pro
tst_Layer.cpp
You can find some info on library projects in "Building a Library" on the Qt website
If, for some reason, you can't move your files around, then you can introduce a new directory for the library, and have it pull in source files from the app directory - but that is definitely more faff, and more confusing:
game
game.pro
app
app.pro - builds only main.o
main.cpp
Entity.h
Entity.cpp
moc_Entity.cpp
lib
lib.pro
Entity.o
moc_Entity.o
tests
layer
layer.pro
tst_Layer.cpp
Edit 2
One problem you have is you are putting object files in to the LIBS variable, which defines what libraries your code will link against. So that'll be why you are getting errors with those files.
Try changing those LIBS uses to OBJECTS instead, and it may work.
If not, have a read of this thread, which is asking pretty much the same thing.
In particular, see the answer by ChrisW67 of '13th May 2012, 10:14' which begins;
Try:
OBJECTS += f1.o f2.o f3.o f3.o
although I think that, if you have the source, building it into your
app directly or via a library is a better option.