Qt MOC failure when building on Windows 10 - c++

I've been using PyQt for years now and had to recode a project in C++ using CLion. I have managed (after awhile) to get the code building on my MacBookPro, but when I move the project to Windows 10, all hell broke loose! I've reloaded mingw with the x86 version and gotten everything to work except MOC and AUTOUIC. The only lines I changed in the CMakeLists.txt file between Oses were the ones that pointed to the Qt install. As I said, I'm new to all this in C++ and may have some 'mistakes' in my makefile, but it works on OSX but not in Windows!
I am able to compile ui and resources files manually and get the build to compile, but I don't know how to resolve this issue.
Any help and guidance would be greatly appreciated!
====================[ Build | crapsStarter | Debug ]============================
C:\Users\a.fireheart.CLion2019.3\system\cygwin_cmake\bin\cmake.exe
--build /cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/cmake-build-debug
--target crapsStarter -- -j 6 [ 14%] Automatic MOC for target crapsStarter
AutoMoc subprocess error
------------------------ The moc process failed to compile "/cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/craps.h"
into
"/cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/cmake-build-debug/crapsStarter_autogen/EWIEGA46WW/moc_craps.cpp".
Command
------- C:/Qt/5.14.1/winrt_x64_msvc2017/bin/moc.exe -I/cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/cmake-build-debug
-I/cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter -I/cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/cmake-build-debug/crapsStarter_autogen/include
-IC:/Qt/5.14.1/winrt_x64_msvc2017/include -IC:/Qt/5.14.1/winrt_x64_msvc2017/include/QtCore -IC:/Qt/5.14.1/winrt_x64_msvc2017/./mkspecs/winrt-x64-msvc2017 -IC:/Qt/5.14.1/winrt_x64_msvc2017/include/QtGui -IC:/Qt/5.14.1/winrt_x64_msvc2017/include/QtANGLE -IC:/Qt/5.14.1/winrt_x64_msvc2017/include/QtWidgets -I/usr/lib/gcc/x86_64-pc-cygwin/9.2.0/include/c++ -I/usr/lib/gcc/x86_64-pc-cygwin/9.2.0/include/c++/x86_64-pc-cygwin -I/usr/lib/gcc/x86_64-pc-cygwin/9.2.0/include/c++/backward -I/usr/lib/gcc/x86_64-pc-cygwin/9.2.0/include -I/usr/include -I/usr/include/w32api -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB --include /cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/cmake-build-debug/crapsStarter_autogen/moc_predefs.h
-o /cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/cmake-build-debug/crapsStarter_autogen/EWIEGA46WW/moc_craps.cpp
/cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/craps.h
Output
make[3]: * [CMakeFiles/crapsStarter_autogen.dir/build.make:58:
CMakeFiles/crapsStarter_autogen] Error 1 make[2]:
[CMakeFiles/Makefile2:104: CMakeFiles/crapsStarter_autogen.dir/all]
Error 2 make[1]: [CMakeFiles/Makefile2:84:
CMakeFiles/crapsStarter.dir/rule] Error 2 make: * [Makefile:118:
crapsStarter] Error 2
***************** My CMakeLists.txt file content *******************************
cmake_minimum_required(VERSION 3.15)
project(crapsStarter)
set(CMAKE_CXX_STANDARD 17)
#set(RESOURCES crapsResources.qrc)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
#set(CMAKE_AUTOUIC ON)
include_directories(cmake-build-debug/crapsStarter_autogen/include)
# Tell cmake where Qt is located
set(Qt5_DIR "C:/Qt/5.14.1/winrt_x64_msvc2017/lib/cmake/Qt5")
set(QT_INCLUDES "C:/Qt/5.14.1/winrt_x64_msvc2017/include")
MESSAGE("QT_INCLUDES: ${QT_INCLUDES}")
# Include a library search using find_package()
# via REQUIRED, specify that libraries are required
set(Qt5 NEED)
find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED)
set(SOURCE_FILES craps.cpp die.cpp crapsGame.cpp crapsResources.cpp)
add_executable(crapsStarter ${SOURCE_FILES})
# specify which libraries to connect
target_link_libraries(${PROJECT_NAME} Qt5::Core)
target_link_libraries(${PROJECT_NAME} Qt5::Gui)
target_link_libraries(${PROJECT_NAME} Qt5::Widgets)
craps.h
//
// Created by Arana Fireheart on 2/2/20.
//
#ifndef CRAPSSTARTER_CRAPS_H
#define CRAPSSTARTER_CRAPS_H
#include "ui_CrapsMainWindow.h"
#include "die.h"
#include <QMainWindow>
class CrapsMainWindow : public QMainWindow, private Ui::CrapsMainWindow {
Q_OBJECT
public:
CrapsMainWindow(QMainWindow *parent = nullptr);
void printStringRep();
void updateUI();
private:
Die die1, die2;
bool firstRoll = true;
int winsCount = 0;
public Q_SLOTS:
void rollButtonClickedHandler();
};
#include "moc_craps.cpp"
#endif //CRAPSSTARTER_CRAPS_H
craps.cpp
#include <iostream>
#include <stdio.h>
//#include <QApplication>
//#include <QWidget>
//#include <QGridLayout>
//#include <QPushButton>
//#include <QLabel>
//#include <QPixmap>
#include "die.h"
#include "craps.h"
#include "ui_CrapsMainWindow.h"
CrapsMainWindow :: CrapsMainWindow(QMainWindow *parent) {
// Build a GUI window with two dice.
setupUi(this);
Die die1, die2;
bool firstRoll = true;
int winsCount = 0;
QObject::connect(rollButton, SIGNAL(clicked()), this, SLOT(rollButtonClickedHandler()));
}
void CrapsMainWindow::printStringRep() {
// String representation for Craps.
char buffer[25];
int length = sprintf(buffer, "Die1: %i\nDie2: %i\n", die1.getValue(), die2.getValue());
printf("%s", buffer);
}
void CrapsMainWindow::updateUI() {
// printf("Inside updateUI()\n");
std::string die1ImageName = ":/dieImages/" + std::to_string(die1.getValue());
std::string die2ImageName = ":/dieImages/" + std::to_string(die2.getValue());
die1UI->setPixmap(QPixmap(QString::fromStdString(die1ImageName)));
die2UI->setPixmap(QPixmap(QString::fromStdString(die2ImageName)));
currentBankValueUI->setText(QString::fromStdString("100"));
}
// Player asked for another roll of the dice.
void CrapsMainWindow::rollButtonClickedHandler() {
//void Craps::rollButtonClickedHandler() {
printf("Roll button clicked\n");
die1.roll();
die2.roll();
printStringRep();
updateUI();
}

Related

Qt5 undefined reference to vtable CMake build issue

i'm decided to build some calculator with CMake, but it failed for some reason, yet it looks correct. I got a set(CMAKE_AUTOMOC ON) rule and yet, what is vtable? I can't simply build it... There are all project files below
CMakeLists.txt
cmake_minimum_required(VERSION 3.1.0)
project(calculator)
set(CMAKE_CXX_COMPILER g++)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC_ON)
set(CMAKE_AUTORCC ON)
find_package(Qt5 COMPONENTS Core Widgets REQUIRED)
include_directories("./include")
add_executable(${PROJECT_NAME} calculator.cpp main.cpp)
target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Widgets)
calculator.hpp
#ifndef CALCULATOR_HPP
# define CALCULATOR_HPP
#include <QtWidgets/QWidget>
#include <QVector>
#include <QLCDNumber>
#include <QPushButton>
class Calculator : public QWidget {
Q_OBJECT
public:
Calculator(QWidget *pwgt = nullptr);
QPushButton *createButton(QString const &rhs);
void calculate();
private:
QLCDNumber *_plcd;
QString _strDisplay;
QVector<QString> _strVector;
public slots:
void buttonClicked();
};
#endif
calculator.cpp
#include <calculator.hpp>
#include <QGridLayout>
Calculator::Calculator(QWidget *pwgt) : QWidget(pwgt) {
QGridLayout *gridObj = new QGridLayout();
_plcd = new QLCDNumber(12);
_plcd->setMode(QLCDNumber::Dec);
_plcd->setSegmentStyle(QLCDNumber::Flat);
_plcd->setMinimumSize(150, 50);
//_wgtPtr = (!_pwgt) ? new QWidget() : pwgt;
QChar calcChars[4][4] = { {'7', '8', '9', '/'},
{'4', '5', '6', '*'},
{'1', '2', '3', '-'},
{'0', '.', '=', '+'}};
gridObj->addWidget(_plcd, 0, 0);
gridObj->addWidget(createButton("CE"), 1, 3);
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j)
gridObj->addWidget(createButton(calcChars[i][j]), i + 2, j);
}
setLayout(gridObj);
}
QPushButton *Calculator::createButton(QString const &rhs) {
QPushButton *calcButton = new QPushButton(rhs);
calcButton->setMinimumSize(40, 40);
connect(calcButton, SIGNAL(clicked()), SLOT(buttonClicked()));
return (new QPushButton(rhs));
}
void Calculator::buttonClicked() {
QString match = dynamic_cast<QPushButton *>(sender())->text();
QRegExp regMatch("[0-9]");
if (!match.compare("CE")) {
_strVector.clear();
_strDisplay.clear();
_plcd->display("0");
} else if (match.contains(regMatch)) {
_strDisplay.push_back(match);
_plcd->display(_strDisplay.toDouble());
} else if (!match.compare(".")) {
_strDisplay.push_back(match);
_plcd->display(_strDisplay.toDouble());
} else {
_strVector.push_back(_strDisplay);
if (_strVector.size() > 1) {
calculate();
_strVector.clear();
_strVector.push_back(_strDisplay);
if (match.compare("="))
_strVector.push_back(match);
} else {
_strVector.push_back(_strDisplay);
_strDisplay.clear();
_plcd->display("0");
}
}
}
void Calculator::calculate() {
double rValue = _strVector.back().toDouble();
_strVector.pop_back();
QString operCalc = _strVector.back();
_strVector.pop_back();
double lValue = _strVector.back().toDouble();
if (!operCalc.compare("+"))
rValue += lValue;
if (!operCalc.compare("-"))
rValue -= lValue;
if (!operCalc.compare("/"))
rValue /= lValue;
if (!operCalc.compare("*"))
rValue *= lValue;
_strDisplay.number(rValue);
_plcd->display(_strDisplay.toDouble());
}
and main.cpp
#include <calculator.hpp>
#include <QApplication>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
Calculator *obj = new Calculator;
obj->resize(230, 200);
obj->setWindowTitle("QtCalculator");
obj->show();
return (app.exec());
}
this is file hierarchy
|--> CMakeLists.txt
|
|--> calculator.cpp
|
|--> main.cpp
|
|--> include
|
|--> calculator.hpp
And this is a build output (in CLion IDE)
====================[ Build | all | Debug ]=====================================
/snap/clion/162/bin/cmake/linux/bin/cmake --build /home/lchantel/train_01Qt/cmake-build-debug --target all -- -j 3
[ 20%] Automatic MOC for target calculator
[ 20%] Built target calculator_autogen
Scanning dependencies of target calculator
[ 40%] Building CXX object CMakeFiles/calculator.dir/calculator_autogen/mocs_compilation.cpp.o
[ 60%] Building CXX object CMakeFiles/calculator.dir/calculator.cpp.o
[ 80%] Building CXX object CMakeFiles/calculator.dir/main.cpp.o
[100%] Linking CXX executable calculator
/usr/bin/ld: CMakeFiles/calculator.dir/calculator.cpp.o: in function `Calculator::Calculator(QWidget*)':
/home/lchantel/train_01Qt/calculator.cpp:4: undefined reference to `vtable for Calculator'
/usr/bin/ld: /home/lchantel/train_01Qt/calculator.cpp:4: undefined reference to `vtable for Calculator'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/calculator.dir/build.make:126: calculator] Error 1
make[1]: *** [CMakeFiles/Makefile2:84: CMakeFiles/calculator.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
Your CMake code needs some work:
Never use include_directories in CMake ever. Use target_include_directories instead.
Always use one of PRIVATE, PUBLIC or INTERFACE with target_link_libraries to avoid weird legacy behavior.
Defining targets in terms ${PROJECT_NAME} is weird, longer, and makes your code less readable for no benefit. There's no compelling reason to keep them coupled and the project name rarely changes.
Never set CMAKE_CXX_COMPILER in your CMakeLists.txt
Prefer compile features to setting CMAKE_CXX_STANDARD.
I seriously doubt you're using CMake 3.1.0. Never set a version lower than the one you're using / testing with.
You have a stray underscore in CMAKE_AUTOUIC_ON
Use this build instead:
cmake_minimum_required(VERSION 3.16)
project(calculator)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
find_package(Qt5 REQUIRED Core Widgets)
add_executable(calculator calculator.cpp main.cpp include/calculator.hpp)
target_link_libraries(calculator PRIVATE Qt5::Core Qt5::Widgets)
target_include_directories(calculator PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_compile_features(calculator PRIVATE cxx_std_11)
The reason you're seeing a vtable error is because moc doesn't see your include/calculator.hpp header because it isn't listed as one of the sources in add_executable.

Error in BlockSci compilation

I was writing a c++ file by calling getTaintedImpl function and I got the below error during its compilation. Could you please be kind enough to help me? Thanks in advance.
The below includes the error, the file which I sed to call the getTaintedImpl (helloworld.cpp) and the CMakefile.txt
Error
/root/BlockSci/tools/test/helloworld.cpp: In function 'int main(int, char**)':
/root/BlockSci/tools/test/helloworld.cpp:53:25: error: 'getTaintedImpl' is not a member of 'blocksci::heuristics'
blocksci::heuristics::getTaintedImpl(func,output,val);
^~~~~~~~~~~~~~
tools/test/CMakeFiles/hello.dir/build.make:62: recipe for target 'tools/test/CMakeFiles/hello.dir/helloworld.cpp.o' failed
make[2]: *** [tools/test/CMakeFiles/hello.dir/helloworld.cpp.o] Error 1
CMakeFiles/Makefile2:730: recipe for target 'tools/test/CMakeFiles/hello.dir/all' failed
make[1]: *** [tools/test/CMakeFiles/hello.dir/all] Error 2
Makefile:151: recipe for target 'all' failed
helloworld.cpp
#include <blocksci/chain/blockchain.hpp>
#include <blocksci/cluster/cluster_manager.hpp>
#include <blocksci/heuristics/change_address.hpp>
#define taint_hpp
#include <blocksci/heuristics/taint.hpp>
#include <blocksci/address/address.hpp>
#include <blocksci/chain/algorithms.hpp>
#include <blocksci/blocksci_export.h>
#include <blocksci/chain/chain_fwd.hpp>
#include <cstdint>
#include <vector>
#include <clipp.h>
#include <iostream>
int main(int argc, char * argv[]) {
std::string dataLocation;
std::string outputLocation;
std::string output;
std::string val;
std::string func;
bool overwrite;
auto cli = (
clipp::value("data location", dataLocation),
clipp::value("output location", outputLocation),
clipp::option("--overwrite").set(overwrite).doc("Overwrite existing cluster files if they exist")
);
auto res = parse(argc, argv, cli);
if (res.any_error()) {
std::cout << "Invalid command line parameter\n" << clipp::make_man_page(cli, argv[0]);
return 0;
}
blocksci::Blockchain chain(dataLocation);
//blocksci::ClusterManager::createClustering(chain, blocksci::heuristics::LegacyChange{}, outputLocation, overwrite);
blocksci::heuristics::getTaintedImpl(func,output,val);
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(hello)
add_executable(hello helloworld.cpp)
target_compile_options(hello PRIVATE -Wall -Wextra -Wpedantic)
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(blocksci_clusterer PRIVATE -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-old-style-cast -Wno-documentation-unknown-command -Wno-documentation -Wno-shadow -Wno-covered-switch-default -Wno-missing-prototypes -Wno-weak-vtables -Wno-unused-macros -Wno-padded)
endif()
target_link_libraries( hello dset)
target_link_libraries( hello clipp)
target_link_libraries( hello blocksci/heuristics)
target_link_libraries(hello blocksci)
install(TARGETS hello DESTINATION bin)

Clion (cmake) won't link the libraries [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm having a problem when trying to link SDL2 and GL libraries to Clion (cmake). Despite changing the cmakelists.txt and adding the target-link-libraries() function. So the cmake file looked like this:
cmake_minimum_required(VERSION 3.9)
project(OpenGL1)
set(CMAKE_CXX_STANDARD 17)
target_link_libraries(OpenGL1 SDL2 GL)
add_executable(OpenGL1 main.cpp Display1.cpp Display1.h)
But with no luck. Clion would not link the libraries with errors such as undifined refference to functions of the libraries.
Then a friend suggested it that I would wite that into cmakelists file:
cmake_minimum_required(VERSION 3.9)
project(OpenGL1)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lGL -lSDL2 -lOpenGL")
add_executable(OpenGL1 main.cpp Display1.cpp Display1.h)
And it kinda worked... But it would not find the -lOpenGL.
Last but not least, my project will not compile with the traditional way in the terminal with g++. And it will compile fine with one .cpp file.
My project consists of 2 cpp files and a header file. Like that:
main.cpp
Display1.cpp
Display.h
And code of the files is the following:
main.cpp
#include <iostream>
#include "Display.h"
using namespace std;
int main() {
Display d1(800,600,"Hello");
while (!d1.m_isClosed()){
d1.Clear(0.0f, 0.15f, 0.3f, 1.0f);
d1.Update();
}
return 0;
}
Display1.cpp
#include "Display.h"
#include <GL/glew.h>
using namespace std;
Display::Display(int width, int height, const string title) {
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE,32);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
m_window = SDL_CreateWindow(title.c_str(),SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,width,height,SDL_WINDOW_OPENGL);
m_glContext = SDL_GL_CreateContext(m_window);
GLenum status = glewInit();
if (status != GLEW_OK)
cerr << "Glew failed!" << endl;
isClosed = false;
}
Display::~Display() {
SDL_GL_DeleteContext(m_glContext);
SDL_DestroyWindow(m_window);
SDL_Quit();
}
void Display::Clear(float r, float g, float b, float a) {
glClearColor(r,g,b,a);
glClear(GL_COLOR_BUFFER_BIT);
}
bool Display::m_isClosed() {
return isClosed;
}
void Display::Update() {
SDL_GL_SwapWindow(m_window);
SDL_Event e;
while (SDL_PollEvent(&e)){
if (e.type == SDL_QUIT)
isClosed = true;
}
}
Display1.h
#ifndef OPENGL_DISPLAY_H
#define OPENGL_DISPLAY_H
#include <iostream>
#include <SDL2/SDL.h>
using namespace std;
class Display {
SDL_Window* m_window;
SDL_GLContext m_glContext;
bool isClosed;
public:
Display(int width, int height, string title);
virtual ~Display();
void Update();
bool m_isClosed();
void Clear(float r, float g, float b, float a);
};
#endif //OPENGL_DISPLAY_H
Now, i know that others have asked the same, but nothing could help me so that's why I'm asking. I'm running Ubuntu 17.10 (64-bit). Thanks in advance!
You have to fix your CMakeLists.txt:
cmake_minimum_required(VERSION 3.9)
project(OpenGL1)
set(CMAKE_CXX_STANDARD 17)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
set(SDL2_INCLUDE_DIRS /usr/include/SDL2)
set(SDL2_LIBRARIES /usr/lib/x86_64-linux-gnu/libSDL2.so)
include_directories(${OPENGL_INCLUDE_DIRS} ${GLEW_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS})
add_executable(OpenGL1 main.cpp Display1.cpp Display1.h)
target_link_libraries(OpenGL1 ${OPENGL_LIBRARIES} ${GLEW_LIBRARIES} ${SDL2_LIBRARIES})
First find the OpenGL files with find_package(OpenGL REQUIRED). Then set the paths for SDL2. Set the include directories for your target (OpenGL1). Add your target. Link libraries to your target.
A better way to use SDL2 is to use FindSDL2.cmake and add find_package(SDL2) to your CMakeLists.txt:
cmake_minimum_required(VERSION 3.9)
project(OpenGL1)
set(CMAKE_CXX_STANDARD 17)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(SDL2 REQUIRED)
include_directories(${OPENGL_INCLUDE_DIRS} ${GLEW_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS})
add_executable(OpenGL1 main.cpp Display1.cpp Display1.h)
target_link_libraries(OpenGL1 ${OPENGL_LIBRARIES} ${GLEW_LIBRARIES} ${SDL2_LIBRARIES})
SDL2 installs its own cmake configuration file called sdl2-config.cmake, so you don't need to download it from github.

Qt Duplicate symbols found for architecture x86_64 [duplicate]

This question already has answers here:
multiple definition of namespace variable, C++ compilation
(3 answers)
Closed 5 years ago.
I have a header file for the namespace Segmentation called segmentation.h. The functions declared in the header are defined in the implementation file segmentation.cpp. The namespace is used in mainwindow.cpp and hence it has been included in the said file. But when I am trying to compile project, I get
1 duplicate symbols found for architecture x86_64
I do understand duplicate symbols found for architecture x86_64 errors occur when you try to include a module multiple times during linkage. But I have only included segmentation.h only once in the above mentioned file.
segmentation.h
#ifndef SEGMENTATION_H
#define SEGMENTATION_H
#include <QObject>
#include <opencv2/opencv.hpp>
#include <QPixmap>
namespace Segmentation
{
int k;
cv::Mat getSegments(cv::Mat inputImage);
cv::Mat sampleInput(cv::Mat &inputImage);
}
#endif // SEGMENTATION_H
segmentation.cpp
#include "segmentation.h"
#include <opencv2/opencv.hpp>
#include <iostream>
cv::Mat Segmentation::getSegments(cv::Mat inputImage)
{
Segmentation::sampleInput(inputImage);
//Incomplete code
return inputImage;
}
cv::Mat Segmentation::sampleInput(cv::Mat &inputImage)
{
std::cout << "Size: " << inputImage.size << std::endl;
std::cout << "Rows: " << inputImage.rows << std::endl;
std::cout << "Cols: " << inputImage.cols << std::endl;
std::cout << "Size rows x cols: " << inputImage.rows * inputImage.cols << std::endl;
//Incomplete code
return inputImage;
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPixmap>
#include <QGraphicsView>
#include <QLabel>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <opencv2/opencv.hpp>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_loadImageButton_clicked();
void on_clearScreenButton_clicked();
void on_segmentButton_clicked();
private:
Ui::MainWindow *ui;
cv::Mat _rawInputImage;
QPixmap _inputImage;
QPixmap _outputImage;
QGraphicsScene _scene;
QGraphicsPixmapItem _inputImagePixmapItem;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QString>
#include <QDebug>
#include <QRectF>
#include <segmentation.h>
MainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(new Ui::MainWindow)
{
ui->setupUi(this);
MainWindow::setWindowState(Qt::WindowFullScreen);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_loadImageButton_clicked()
{
QFileDialog fileDialog(this, Qt::Dialog);
fileDialog.setFileMode(QFileDialog::ExistingFile);
fileDialog.setNameFilter("*.jpg *.png *.jpeg");
fileDialog.setViewMode(QFileDialog::Detail);
fileDialog.exec();
QStringList selectedFileName = fileDialog.selectedFiles();
QString selectedFile = selectedFileName.at(0);
_inputImage.load(selectedFile);
_rawInputImage = cv::imread(selectedFile.toStdString());
_inputImagePixmapItem.setPixmap((_inputImage));
_scene.addItem(&_inputImagePixmapItem);
this->ui->inputImageViewWidget->setScene(&_scene);
this->ui->inputImageViewWidget->fitInView(&_inputImagePixmapItem, Qt::KeepAspectRatio);
fileDialog.saveState();
return;
}
void MainWindow::on_clearScreenButton_clicked()
{
_scene.removeItem(&_inputImagePixmapItem);
return;
}
void MainWindow::on_segmentButton_clicked()
{
cv::Mat segmentedOutputImage = Segmentation::getSegments(_rawInputImage);
}
Compile output
14:15:59: Running steps for project LaundroBotQt...
14:15:59: Configuration unchanged, skipping qmake step.
14:15:59: Starting: "/usr/bin/make"
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -headerpad_max_install_names -stdlib=libc++ -Wl,-syslibroot,/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -mmacosx-version-min=10.9 -Wl,-rpath,/Users/Vino/Documents/Qt/5.8/clang_64/lib -o LaundroBotQt.app/Contents/MacOS/LaundroBotQt main.o mainwindow.o segmentation.o moc_mainwindow.o -F/Users/Vino/Documents/Qt/5.8/clang_64/lib -L/usr/local/lib -lopencv_core -lopencv_imgcodecs -lopencv_highgui -lopencv_features2d -lopencv_ml -lopencv_flann -lopencv_imgproc -lopencv_photo -framework QtWidgets -framework QtGui -framework QtCore -framework DiskArbitration -framework IOKit -framework OpenGL -framework AGL
duplicate symbol __ZN12Segmentation1kE in:
mainwindow.o
segmentation.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [LaundroBotQt.app/Contents/MacOS/LaundroBotQt] Error 1
14:15:59: The process "/usr/bin/make" exited with code 2.
Error while building/deploying project LaundroBotQt (kit: Desktop Qt 5.8.0 clang 64bit)
When executing step "Make"
14:15:59: Elapsed time: 00:01.
GitHub repo link
I am not quite sure how to fix this problem. I have read through StackOverflow, but my issue seems bizarre. Any help is appreciated.
The problem is here, in segmentation.h:
namespace Segmentation
{
int k;
[...]
Here you are both declaring and defining storage for the variable named k in the Segmentation namespace. The problem with that is that if more than one .cpp file #include's segmentation.h (which will almost certainly happen), then the variable Segmentation::k will have storage declared for it in more than one .cpp file, leading to the duplicate-symbols error you see.
To get around that problem, do this in segmentation.h instead:
namespace Segmentation
{
extern int k;
[...]
... and then in one of your .cpp files (probably segmentation.cpp would be the most appropriate one), add the storage separately, like this:
namespace Segmentation
{
int k;
};
That way storage space for Segmentation::k will be allocated only in that one .cpp file instead of many of them.

Why can't my C++ classes use Qt?

I'm working on a very basic C++ application using Qt5.6 with CMake. Git Repo Here.
My problem? My main.cpp can #include Qt classes like <QtCore/QObject>, but my defined classes cannot.
error: QtCore/QObject: No such file or directory
I have downloaded the latest version of Qt with Qt Creator here.
Could this be an improperly set up Qt environment? I don't understand how main.cpp can access Qt but my defined classes cannot.
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.11)
project(testproject)
# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)
############ OpenCV PACKAGE #########
set(BUILD_SHARED_LIBS ON)
set(OpenCV_FIND_QUIETLY FALSE)
find_package( OpenCV REQUIRED)
include_directories( ${OpenCV_INCLUDE_DIRS} )
# Find the QtWidgets library
find_package(Qt5Widgets)
qt5_wrap_cpp(tcp_hdr_moc ${PROJECT_SOURCE_DIR}/TcpServer.h)
# Tell CMake to create the helloworld executable
add_executable(helloworld WIN32 main.cpp
TcpServer.h TcpServer.cpp
)
# Use the Widgets module from Qt 5.
target_link_libraries(helloworld Qt5::Widgets
${OpenCV_LIBS}
${PROJECT_SOURCE_DIR}/TcpServer.cpp
${PROJECT_SOURCE_DIR}/TcpServer.h
)
main.cpp
#include <iostream>
#include <QtWidgets/QApplication>
#include <QtCore/QObject>
//#include "TcpServer.h"
using namespace std;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString test = "Hello";
QObject test2;
int i = 0;
// TcpServer server;
}
User defined class: TcpServer.cpp
#include "TcpServer.h"
#include <QtNetwork/QTcpSocket>
#include <QtCore/QByteArray>
#include <QtCore/QtDebug>
#include <QtCore/QString>
#include <opencv2/core.hpp>
#include <opencv2/opencv.hpp>
TcpServer::TcpServer(QObject *parent) :
QObject(parent)
{
server = new QTcpServer(this);
// whenever a user connects, it will emit signal
connect(server, SIGNAL(newConnection()),
this, SLOT(newConnection()));
if (!server->listen(QHostAddress::Any, 9999))
qDebug() << "Server could not start";
else
qDebug() << "Server started!";
vCapture = new VideoCapture(0);
}
void TcpServer::newConnection()
{
QTcpSocket *socket = server->nextPendingConnection();
QByteArray ContentType = ("HTTP/1.0 200 OK\r\n" \
"Cache-Control: no-cache\r\n" \
"Cache-Control: private\r\n" \
"Content-Type: multipart/x-mixed-replace;boundary=--boundary\r\n");
socket->write(ContentType);
std::vector<uchar> buff;
Mat img; //OpenCV Material
while (1) {
// Image to Byte Array via OPENCV Method
buff.clear();buff.empty();
vCapture->read(img); //Read from webcam
//TODO set the compression parameters.
imencode(".jpg", img, buff);
std::string content(buff.begin(), buff.end());
QByteArray CurrentImg(QByteArray::fromStdString(content));
QByteArray BoundaryString = ("--boundary\r\n" \
"Content-Type: image/jpeg\r\n" \
"Content-Length: ");
BoundaryString.append(QString::number(CurrentImg.length()));
BoundaryString.append("\r\n\r\n");
socket->write(BoundaryString);
socket->write(CurrentImg); // Write The Encoded Image
socket->flush();
}
}
User Defined Class Header which throws the error: TcpServer.h
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include <QtCore/QObject>
#include <QtNetwork/QTcpServer>
#include "opencv2/videoio.hpp"
using namespace cv;
class TcpServer : public QObject
{
Q_OBJECT
public:
explicit TcpServer(QObject *parent = 0);
void newConnection();
private:
QTcpServer* server;
VideoCapture* vCapture;
};
#endif
For reference I am working on these two related stack overflow questions.
How to Create a HTTP MJPEG Streaming Server With QTcp-Server Sockets?
Error while using QTcpSocket.
Add find_package(Qt5Core) in addition to find_package(Qt5Widgets) and add the following lines:
include_directories(${Qt5Widgets_INCLUDE_DIRS})
include_directories(${Qt5Core_INCLUDE_DIRS})
And do not forget to add Qt5::Core to the target_link_libraries.
BTW, I see you are using QtNetwork; you will have to make the same steps for that module too. And for every other module you will use.