I have this sample code that reproduces the problem I am dealing with.
//main.cpp
#include "widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
widget w;
w.show();
return a.exec();
}
--
//widget.h
#pragma once
#include <QMainWindow>
#include <QPushButton>
#include <QApplication>
#include <QLayout>
class widget : public QMainWindow
{
Q_OBJECT
public:
QApplication* application;
widget(QWidget *parent = nullptr);
QVBoxLayout *mainLayout;
QPushButton *startButton;
QWidget *centralWidget;
~widget();
public slots:
void onStartButtonPressed();
private:
void start();
bool loop;
};
--
//widget.cpp
#include "widget.h"
widget::widget(QWidget *parent)
: QMainWindow(parent)
{
application = static_cast<QApplication*>(QApplication::instance());
mainLayout = new QVBoxLayout();
loop = false;
startButton = new QPushButton("START");
mainLayout->addWidget(startButton);
connect(startButton, SIGNAL(clicked()),this,SLOT(onStartButtonPressed()));
centralWidget = new QWidget();
centralWidget->setLayout(mainLayout);
this->setCentralWidget(centralWidget);
this->showMaximized();
this->setWindowTitle("Widget");
}
void widget::onStartButtonPressed()
{
loop = !loop;
startButton->setText(loop? "STOP" : "START");
start();
}
void widget::start()
{
while(loop)
{
application->processEvents();
}
}
widget::~widget()
{
loop = false;
}
This is a simple Qt application with a QPushButton that when pressed set a boolean flag to true and starts a loop. When the main widget is closed the destructor sets boolean flag to false and the loop should break.
However when loop is running the destructor seems not been called, while when loop is not running it is called normally and the app quit accordingly.
Of course I call application->processEvents() to prevent freezing, but I don't know why the destructor is not called at loop running.
Related
I have directly tried to convert C++ example of mathGL Into C code here:
#include <mgl2/mgl_cf.h>
#include <mgl2/wnd_cf.h>
#include <mgl2/fltk.h>
#include <pthread.h>
#include <synchapi.h>
//mglFLTK *gr=NULL; // pointer to window
HMGL gr = NULL;//HMGL mgl_create_graph_fltk
void *calc(void *) // function with calculations
{
// mglPoint pnt; // some data for plot
// HMDT dat;
// dat= mgl_create_data () ;
for(long i=0;;i++) // do calculation
{
// long_calculations(); // which can be very long
// Sleep(200);
for(uint64_t i=0;i<200000;i++);
// pnt.Set(2*mgl_rnd()-1,2*mgl_rnd()-1);
if(gr)
{
// gr->Clf(); // make new drawing
mgl_clf ( gr) ;
// draw something
// gr->Line(mglPoint(),pnt,"Ar2");
mgl_line(gr,0,0,0,2*mgl_rnd()-1,2*mgl_rnd()-1,0,"Ar2",2);
char str[16]; snprintf(str,15,"i=%ld",i);
// gr->Puts(mglPoint(),str);
mgl_puts(gr,0,0,0,str,":C",-.7);
// don’t forgot to update window
// gr->Update();
mgl_wnd_update(gr);
}
}
}
But it doesn't work. I've added printf before mgl_wnd_update to printing i in console and it only prints one time: i=0. I'm using windows 10 and installed minGW GCC and mathgl by MSYS2 through eclipse IDE. Though I've created the not threaded one here:
int main(int argc,char **argv)
{
gr = mgl_create_graph_fltk(NULL, "First C graph", NULL, NULL);
mgl_fltk_thr ();
while(1)
{
Sleep(100);
mgl_clf ( gr) ;
// draw something
// gr->Line(mglPoint(),pnt,"Ar2");
mgl_line(gr,0,0,0,2*mgl_rnd()-1,2*mgl_rnd()-1,0,"Ar2",-.5);
char str1[16]; snprintf(str1,15,"i=%ld",1);
// gr->Puts(mglPoint(),str);
mgl_puts(gr,0,0,0,str1,":C",-.5);
// don’t forgot to update window
// gr->Update();
mgl_wnd_update(gr);
}
return 0;
}
And this is works. What is wrong with that pthreaded code? It seems that the thread loop only works once. But this loops works well on none-threade program!!
So I recently started with C at exercism page.
I currently facing a rather simple challenge.
Determine if a word or phrase is an isogram.
An isogram (also known as a "non-pattern word") is a word or phrase without a repeating letter, however spaces and hyphens are allowed to appear multiple times.
Examples of isograms:
lumberjacks
background
downstream
six-year-old
The word isograms, however, is not an isogram, because the s repeats.
There are 15 tests in total, of which one specific is not passed:
test_isogram_with_duplicated_hyphen
I guess test number 15 also passes because of some error I don't see
Here's the testing code:
#include "test-framework/unity.h"
#include "isogram.h"
#include <stdlib.h>
void setUp(void)
{
}
void tearDown(void)
{
}
static void test_empty_string(void)
{
TEST_ASSERT_TRUE(is_isogram(""));
}
static void test_null(void)
{
TEST_IGNORE(); // delete this line to run test
TEST_ASSERT_FALSE(is_isogram(NULL));
}
static void test_isogram_with_only_lower_case_characters(void)
{
TEST_IGNORE();
TEST_ASSERT_TRUE(is_isogram("isogram"));
}
static void test_word_with_one_duplicated_character(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("eleven"));
}
static void test_word_with_one_duplicated_character_from_end_of_alphabet(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("zzyzx"));
}
static void test_longest_reported_english_isogram(void)
{
TEST_IGNORE();
TEST_ASSERT_TRUE(is_isogram("subdermatoglyphic"));
}
static void test_word_with_duplicated_letter_in_mixed_case(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("Alphabet"));
}
static void test_word_with_duplicated_letter_in_mixed_case_lowercase_first(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("alphAbet"));
}
static void test_hypothetical_isogrammic_word_with_hyphen(void)
{
TEST_IGNORE();
TEST_ASSERT_TRUE(is_isogram("thumbscrew-japingly"));
}
static void
test_hypothetical_word_with_duplicated_character_following_hyphen(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("thumbscrew-jappingly"));
}
static void test_isogram_with_duplicated_hyphen(void)
{
TEST_IGNORE();
TEST_ASSERT_TRUE(is_isogram("six-year-old"));
}
static void test_made_up_name_that_is_an_isogram(void)
{
TEST_IGNORE();
TEST_ASSERT_TRUE(is_isogram("Emily Jung Schwartzkopf"));
}
static void test_duplicated_character_in_the_middle(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("accentor"));
}
static void test_same_first_and_last_characters(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("angola"));
}
static void test_word_with_duplicated_character_and_with_two_hyphens(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("up-to-date"));
}
int main(void)
{
UnityBegin("test_isogram.c");
RUN_TEST(test_empty_string);
RUN_TEST(test_null);
RUN_TEST(test_isogram_with_only_lower_case_characters);
RUN_TEST(test_word_with_one_duplicated_character);
RUN_TEST(test_word_with_one_duplicated_character_from_end_of_alphabet);
RUN_TEST(test_longest_reported_english_isogram);
RUN_TEST(test_word_with_duplicated_letter_in_mixed_case);
RUN_TEST(test_word_with_duplicated_letter_in_mixed_case_lowercase_first);
RUN_TEST(test_hypothetical_isogrammic_word_with_hyphen);
RUN_TEST(test_hypothetical_word_with_duplicated_character_following_hyphen);
RUN_TEST(test_isogram_with_duplicated_hyphen);
RUN_TEST(test_made_up_name_that_is_an_isogram);
RUN_TEST(test_duplicated_character_in_the_middle);
RUN_TEST(test_same_first_and_last_characters);
RUN_TEST(test_word_with_duplicated_character_and_with_two_hyphens);
return UnityEnd();
}
This is my code:
#include "isogram.h"
#include <stdlib.h>
#include <stdio.h>
/* gives new char array from input, only small letters */
char* clean_words(char* ptr_input)
{
// new container; everything bigger than 27 is impossible to be an isogram
static char cleaned[27] = {"00000000000000000000000000"};
int i = 0, j = 0, k = 0;
for (int i = 0; ptr_input[i] != '\000'; i++)
{
k++;
}
for (i=0; i <= k; i++, j++)
{
if (ptr_input[i] > 64 && ptr_input[i] < 91)
{
cleaned[j] = ptr_input[i] + 32;
}
else if (ptr_input[i] > 96 && ptr_input[i] < 123)
{
cleaned[j] = ptr_input[i];
}
else
{
j--;
}
}
char* ptr_output = &cleaned[0];
return ptr_output;
}
bool is_isogram(char phrase[])
{
if(phrase == NULL)
{ return false; }
char* ptr_a = clean_words(phrase);
char ca_empty[27] = {"00000000000000000000000000"};
for(int i = 0; i <= 27; i++, ptr_a++){
// first element is always copied
if(i == 0){
ca_empty[i] = *ptr_a;
continue;
}
// '0' is sentinel, meaning the input word is finished => exit loop.
if(*ptr_a == '0' || *ptr_a == '\000')
{ break; }
// following elements only copied if different than current input char
int j = 0;
// loop copied for doubles, exit when found
for(;j<i;j++)
{
if(ca_empty[j] == *ptr_a){
return false;
}
}
// if none was found, copy new letter
ca_empty[i] = *ptr_a;
}
return true;
}
So basically I solve this in 2 steps. First, I will reduce any input to small letters only. Second, I copy letter by letter to a new container and test doubles before every copy process.
Yes, there are certainly fancier solutions, but I'd like to know if anyone can spot why I get FAILED on "six-year-old". Especially, when it is working locally. Thanks! :-)
So I figured it out by myself:
The problem is the helper function clean_words.
The char array cleaned is declared as static. That means it will keep its value even after the current block is finished.
When the tests run through, cleaned will still contain remaining letters of the input from other tests. The solution would be removing the static keywird or implementing a way to clean up the container, like
memset(cleaned, '0', 26);
From https://en.cppreference.com/w/c/language/storage_duration
static storage duration.
The storage duration is the entire execution of the program, and the value stored in the object is initialized only once, prior to main function. All objects declared static and all objects with either internal or external linkage that aren't declared _Thread_local (since C11) have this storage duration.
I have a problem in using QTimer command.
I dont have any syntax error, but i have 2 error in qglobal.h and qobjectdefs_impl.h and i dont understand them.
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
void MainWindow::updatewindow()
{
Mat frame;
capture >> frame;
cvtColor(frame, frame, cv::COLOR_BGR2RGB);
QImage image((uchar*)frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888);
QPixmap temp_img = QPixmap::fromImage(image);
ui->label2->setPixmap(temp_img);
}
void MainWindow::on_pushload_clicked()
{
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, SLOT(updatewindow()));
timer->start(20);
}
I have a problem in using QTimer command.
I dont have any syntax error, but i have 2 error in qglobal.h and qobjectdefs_impl.h and i dont understand them.
and mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPixmap>
#include <QTimer>
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
QPixmap Iblackwhite,IMG_Color{};
QImage image {};
cv::VideoCapture capture{};
private slots:
void updatewindow();
void on_pushload_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
please help me to solve my problem.
Use &MainWindow::updateWindow instead of SLOT(updatewindow()).
My task would be to make this object hierarchy and have a sum of all file sizes in the file system.
If I understand correctly this would be a multi level inheritance, but I'm not sure how to write a function what can run through every lower-level object and sum them up.
#include <iostream>
using namespace std;
class File{
public:
//File(int x){filesize=x;}
void setSize(int x){filesize=x;}
void showsize(){cout<<filesize<<endl;}
int getsize(){return filesize;}
private:
int filesize;
};
class Directory : public File {
public:
void SumDir(){
}
private:
int sumofdir=0;
};
int main()
{
File b;
b.setSize(416);
b.showsize();
return 0;
}
You could have the Directory class have a std::vector of File*. Then it would be just a simple walkthrough of each of these directory entries and in turn, invoke the getSize() on them. getSize() could be a polymorphic function that just either gets the size of the File if it's a regular file or the size of the entire directory if it's an instance of a Directory. Something on these lines:
#include <iostream>
#include <vector>
class File{
public:
explicit File(int x): fileSize(x){}
void setSize(int x){
fileSize=x;
}
void showSize() const{
std::cout<<fileSize<<'\n';
}
virtual size_t getSize() const{
return fileSize;
}
virtual ~File() = default;
private:
int fileSize;
};
class Directory : public File {
public:
Directory() : File(0){} //Directory is just a File of 0 size
size_t getSize() const override{
size_t size = 0;
for(auto const& file: dirEntries) {
size += file->getSize();
}
return size;
}
void addFile(File* file) {
if(file != nullptr) {
dirEntries.push_back(file);
}
}
private:
std::vector<File*> dirEntries;
};
int main() {
Directory child;
File f1{10}, f2{20};
child.addFile(&f1);
child.addFile(&f2);
Directory parent;
File f3{30};
parent.addFile(&f3);
parent.addFile(&child);
std::cout<<parent.getSize(); //60
}
I have:
car.cc
#include "car.h"
#include <iostream>
using namespace std;
extern "C" Car* create_object()
{
return new Car;
}
Car::Car() {
this->maxGear = 2;
this->currentGear = 1;
this->speed = 0;
}
void Car::shift(int gear) {
if (gear < 1 || gear > maxGear) {
return;
}
currentGear = gear;
}
void Car::brake() {
speed -= (5 * this->getCurrentGear());
std::cout<<"THE SPEED IS:" <<speed<<std::endl;
}
extern "C" void destroy_object( Car* object )
{
delete object;
}
car.h
#ifndef VEHICLES_CAR_H
#define VEHICLES_CAR_H
// A very simple car class
class Car {
public:
Car();
void shift(int gear);
void accelerate();
void brake();
private:
int maxGear;
int currentGear;
int speed;
};
#endif /* VEHICLES_CAR_H */
test.cc
#include "/home/car.h"
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int main()
{
/* on Linux, use "./myclass.so" */
void* handle = dlopen("/usr/lib/libCarTest.so", RTLD_LAZY);
int (*result)(int);
if (!handle)
{
}
/*dlsym(handle,"accelerate");
cout<<"IN HERE: "<<endl;
dlsym(handle,"brake");
dlclose(handle);*/
Car* (*create)();
void (*destroy)(Car*);
dlerror();
create = (Car* (*)())dlsym(handle, "create_object");
destroy = (void (*)(Car*))dlsym(handle, "destroy_object");
Car* carr = (Car*)create();
carr->brake();
destroy( carr );
dlclose(handle);
/*
Car carr;
carr.brake();
* compilation g++ test.cpp -o tst /path/libcar.so
*/
return 0;
}
After creating libMyLib.so and install it in /usr/lib i've tried to compile test.cc using: g++ test.cc -o tst -ldl. WHY do i need to include -lMyLib? is there a way to compile the code without libMyLib.so? Secondly why dlsym(handle,"brake") is not working? If i change dlsym (Car* (*).... with dlsym(handle,"brake") i get nothing. why?
Appreciate
WHY do i need to include -lMyLib?
Because you need to link to the Car::brake method.
Secondly why dlsym(handle,"brake") is not working?
Because there is no brake symbol. The method Car::brake has a complicated mangled (implementation-defined) name. You can see this in the output of nm -D.
AFAIK, you can solve it by
making all the methods of Car virtual (they will be called through a pointer, so no linking will be needed)
doing it the old C way, ie. export a free function brake() that would call the Car::brake method from the .so
making all the public methods of Car inline and defining them in the header.
emulating the virtual table approach (as we do it in C)
Combining the last two approaches:
class Car {
public:
void brake() { brake_impl(this); }
private:
void (*brake_impl)(Car*);
void do_brake(); // this would be the actual implementation
Car() : brake_impl([] (Car* c){ c->do_brake(); }) { ... }
};
Of course you could split the implementation and the interface so it's not such a mess.