Incorrect checksum for freed object in c++/sfml application - multithreading

I am trying to create a multiplayer game where players can use voice chat to communicate.
I am using C++ and SFML-3.0 for everything.
Here is the GitHub page for the whole project: https://github.com/iwannabespace/test
First of all, here are some of the classes that I am using:
AudioCapturer.hpp
class AudioCapturer : public sf::SoundStream
{
public:
AudioCapturer(Client& client);
void receiveLoop(sf::Packet& packet);
private:
bool onGetData(sf::SoundStream::Chunk& data) override;
void onSeek(sf::Time timeOffset) override;
private:
std::recursive_mutex mutex;
std::vector<std::int16_t> samples;
std::vector<std::int16_t> tempbuffer;
size_t offset;
Client& client;
};
AudioCapturer.cpp
AudioCapturer::AudioCapturer(Client& client)
: offset(0), client(client)
{
initialize(1, 44100);
}
bool AudioCapturer::onGetData(sf::SoundStream::Chunk& data)
{
while (offset >= samples.size())
sf::sleep(sf::milliseconds(10));
{
std::scoped_lock lock(mutex);
tempbuffer.assign(samples.begin() + static_cast<std::vector<std::int64_t>::difference_type>(offset),
samples.end());
std::cout << "Tempbuffer address: " << &tempbuffer << std::endl;
}
data.samples = tempbuffer.data();
data.sampleCount = tempbuffer.size();
offset += tempbuffer.size();
return true;
}
void AudioCapturer::onSeek(sf::Time timeOffset)
{
offset = static_cast<std::size_t>(timeOffset.asMilliseconds()) * getSampleRate() * getChannelCount() / 1000;
}
void AudioCapturer::receiveLoop(sf::Packet& packet)
{
while (true)
{
if (client.receivedAudio)
{
sf::Packet copy = packet;
std::uint8_t command;
if (copy >> command)
{
std::size_t sampleCount = (copy.getDataSize() - 1) / sizeof(std::int16_t);
{
std::scoped_lock lock(mutex);
std::size_t oldSize = samples.size();
samples.resize(oldSize + sampleCount);
std::cout << "Samples address: " << &samples << std::endl;
std::cout << "Last item address: " << &samples[oldSize] << std::endl;
std::memcpy(&(samples[oldSize]),
static_cast<const char*>(copy.getData()) + 1,
sampleCount * sizeof(std::int16_t));
}
client.receivedAudio = false;
}
}
}
}
Client.hpp
class Client
{
public:
Client(const sf::IpAddress& ip, int port);
~Client();
bool connect();
void disconnect();
bool send(sf::Packet& packet);
bool receivePacket(sf::Packet& packet, std::unordered_map<std::uint32_t, Player>& players, std::uint32_t& thisPlayer);
public:
bool receivedAudio;
bool receivedPosition;
private:
int port;
sf::IpAddress ip;
sf::TcpSocket socket;
};
Client.cpp
Client::Client(const sf::IpAddress& ip, int port)
: ip(ip), port(port), receivedAudio(false), receivedPosition(false)
{
}
Client::~Client()
{
}
bool Client::connect()
{
if (socket.connect(ip, port) != sf::Socket::Done)
return false;
return true;
}
void Client::disconnect()
{
socket.disconnect();
}
bool Client::send(sf::Packet& packet)
{
if (socket.send(packet) != sf::Socket::Done)
return false;
return true;
}
bool Client::receivePacket(sf::Packet& packet, std::unordered_map<std::uint32_t, Player>& players, std::uint32_t& thisPlayer)
{
sf::Packet recv;
sf::Packet copy;
while (true)
{
if (socket.receive(recv) != sf::Socket::Done)
return false;
if (receivedAudio)
std::cout << "Data is not used!" << std::endl;
std::uint8_t command;
std::uint32_t id;
copy = recv;
if (copy >> command)
{
switch (command)
{
case ServerCommand::ADD_PLAYER:
copy >> id;
if (thisPlayer == 0)
{
thisPlayer = id;
std::cout << "My id is " << thisPlayer << std::endl;
}
players[id] = Player(5.f, id);
std::cout << "Player joined!" << std::endl;
break;
case ServerCommand::ADD_PLAYERS:
while (copy >> id)
players[id] = Player(5.f, id);
break;
case ServerCommand::RECEIVE_AUDIO:
receivedAudio = true;
packet = recv;
break;
case ServerCommand::RECEIVE_POSITION:
receivedPosition = true;
packet = recv;
break;
default:
break;
}
}
}
return true;
}
AudioRecorder.hpp
class AudioRecorder : public sf::SoundRecorder
{
public:
AudioRecorder(Client& client);
~AudioRecorder() override;
void activeness();
void setActive(bool active);
bool isActive() const;
private:
bool onStart() override;
bool onProcessSamples(const std::int16_t* samples, std::size_t sampleCount) override;
void onStop() override;
private:
Client& client;
bool active;
std::mutex mutex;
};
AudioRecorder.cpp
AudioRecorder::AudioRecorder(Client& client)
: client(client), active(false)
{
}
AudioRecorder::~AudioRecorder()
{
stop();
}
void AudioRecorder::activeness()
{
while (true)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) && !active)
{
std::scoped_lock lock(mutex);
active = true;
if (start()) {}
}
if (!sf::Keyboard::isKeyPressed(sf::Keyboard::Space) && active)
{
std::scoped_lock lock(mutex);
stop();
active = false;
}
}
}
void AudioRecorder::setActive(bool active)
{
this->active = active;
}
bool AudioRecorder::isActive() const
{
return active;
}
bool AudioRecorder::onStart()
{
std::cout << "Started!" << std::endl;
return true;
}
bool AudioRecorder::onProcessSamples(const std::int16_t* samples, std::size_t sampleCount)
{
sf::Packet packet;
packet << ServerCommand::RECEIVE_AUDIO;
packet.append(samples, sampleCount * sizeof(std::int16_t));
return client.send(packet);
}
void AudioRecorder::onStop()
{
std::cout << "Stopped!" << std::endl;
}
main.cpp
int main()
{
std::srand(std::time(0));
Client client("127.0.0.1", 4242);
if (client.connect())
{
std::cout << "Connected to server!" << std::endl;
sf::RenderWindow window(sf::VideoMode({ 1280, 720 }), "Multiplayer Game", sf::Style::Default);
window.setVerticalSyncEnabled(true);
sf::View view;
view.setCenter({ 640, 360 });
view.setSize(sf::Vector2f(window.getSize()));
sf::Packet packet;
std::unordered_map<std::uint32_t, Player> players;
std::uint32_t thisPlayer = 0;
StartScreen startscreen(window, sf::Color(172, 192, 146));
AudioRecorder recorder(client);
AudioCapturer capturer(client);
capturer.play();
std::thread receivePacket;
std::thread receiverloop;
std::thread activeness;
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
switch (event.type)
{
case sf::Event::Closed:
window.close();
break;
case sf::Event::Resized:
if (startscreen)
{
view.setCenter({
static_cast<float>(window.getSize().x) / 2,
static_cast<float>(window.getSize().y) / 2
});
view.setSize(sf::Vector2f(window.getSize()));
startscreen.updateOnResize();
}
break;
}
}
if (!receivePacket.joinable())
receivePacket = std::thread(&Client::receivePacket, std::ref(client), std::ref(packet), std::ref(players), std::ref(thisPlayer));
if (!receiverloop.joinable())
receiverloop = std::thread(&AudioCapturer::receiveLoop, std::ref(capturer), std::ref(packet));
if (!activeness.joinable())
activeness = std::thread(&AudioRecorder::activeness, std::ref(recorder));
if (client.receivedPosition)
{
sf::Packet copy = packet;
std::uint8_t command;
if (copy >> command)
{
float x, y;
std::uint32_t id;
copy >> id >> x >> y;
for (auto& player : players)
if (player.first == id)
player.second.setPosition({ x, y });
client.receivedPosition = false;
}
}
if (window.hasFocus())
players[thisPlayer].move(client);
window.clear(sf::Color::White);
window.setView(view);
for (const auto& player : players)
window.draw(player.second);
window.display();
}
client.disconnect();
std::terminate();
}
return 0;
}
I know it's a lot of code and I am sorry that I have to share too much.
I believe the problem is with the AudioCapturer class. For some reason when sending audio data, after a while client that receives it stops the execution and prompts this problem with different addresses:
a.out(60911,0x16b47b000) malloc: Incorrect checksum for freed object 0x12a80a400: probably modified after being freed.
Corrupt value: 0xe7026101a000bcff
By the way I am kind of using the SFML's VoIP example for the AudioCapturer class.
This is the Github page of it: https://github.com/SFML/SFML/blob/master/examples/voip/Server.cpp
I'd appreciate it If someone can help me with that problem.

Related

getting response only on the first time with socket programming

I'm trying to create an HTTP server using C++ 98.
The issue is that, every time I launch my server, I get the response, sending again the request from the same browser tab, and the browser keeps loading.
In my kqueue, it seems like the block for checking the read event is not being executed on the second time.
This is my code:
void webserv::Server::lunch(){
this->kq.create_event(this->sock.getSocket(), EVFILT_READ);
while(1)
this->_lunch_worker();
}
void webserv::Server::_lunch_worker(void)
{
int n_ev;
int accept_sock;
int address_size;
char buff[1000];
webserv::Header header;
// register the events in ev_list
std::cout << GREEN << "---- WAITING FOR CONNECTION ----" << RESET << std::endl;
n_ev = this->kq.get_event();
for (int i = 0; i < n_ev; i++)
{
if (this->kq.get_fd(i) < 0)
continue;
if (this->kq.get_fd(i) == this->sock.getSocket())
{
std::cout << "--- RECEIVED NEW CONNECTION ---" << std::endl;
address_size = sizeof(this->sock.getAddress());
accept_sock = accept(
this->sock.getSocket(),
(struct sockaddr*)&this->sock.getAddress(),
(socklen_t *)&address_size
);
this->sock.test_error(accept_sock);
this->kq.create_event(accept_sock, EVFILT_READ);
int flags;
if ((flags = fcntl(accept_sock, F_GETFL, 0)) < 0) {
perror("fcntl");
close(accept_sock);
close(this->sock.getSocket());
}
if (fcntl(accept_sock, F_SETFL, flags | O_NONBLOCK) < 0) {
perror("fcntl");
close(accept_sock);
close(this->sock.getSocket());
}
this->kq.create_event(accept_sock, EVFILT_WRITE, EV_ADD | EV_ONESHOT);
}
else if (this->kq.is_read_available(i))
{
int bytes_read;
std::cout << "START: is_read_available" << std::endl;
if ((bytes_read = recv(this->kq.get_fd(i), buff, 999, 0)) > 0)
{
}
}
else if (this->kq.is_write_available(i))
{
std::string hello = "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 12\n\nHello world!";
if (send(this->kq.get_fd(i), hello.c_str(), hello.length(), 0) != 0)
{
std::cout << "TEST2" << std::endl;
this->kq.set_event(this->kq.get_fd(i), EVFILT_WRITE, EV_DELETE);
this->kq.get_event_list()[i].ident = -1;
close(this->kq.get_fd(i));
}
std::cout << "END: is_write_available" << std::endl;
}
}
}
And this is the kqueue class:
/************************ CONSTRUCTORS/DESTRUCTOR ************************/
webserv::Kqueue::Kqueue()
{
this->_kq = kqueue();
std::cout << "KQUEUE CREATED" << std::endl;
this->test_error(this->_kq, "Creating Kqueue :");
this->_n_ev = 0;
}
webserv::Kqueue::~Kqueue()
{
close(this->_kq);
}
/************************ MEMBER FUNCTIONS ************************/
void webserv::Kqueue::set_event(int fd, int filter, int flags, void *udata)
{
EV_SET(&this->_ev_set, fd, filter, flags, 0, 0, udata);
}
void webserv::Kqueue::add_event(void)
{
int ret;
ret = kevent(this->_kq, &this->_ev_set, 1, NULL, 0, NULL);
this->test_error(ret, "Kqueue/add_even functions");
}
int webserv::Kqueue::get_event(void)
{
this->_n_ev = kevent(this->_kq, NULL, 0, this->_ev_list, __EV_LIST_SIZE__, NULL);
this->test_error(this->_n_ev, "Kqueue/get_event function:");
return (this->_n_ev);
}
void webserv::Kqueue::create_event(int fd, int filter, int flags, void *udata)
{
this->set_event(fd, filter, flags, udata);
this->add_event();
}
bool webserv::Kqueue::isEOF(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/isEOF function:");
return (this->_ev_list[index].flags & EV_EOF);
}
bool webserv::Kqueue::is_read_available(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/is_read_available function:");
return (this->_ev_list[index].filter == EVFILT_READ);
}
bool webserv::Kqueue::is_write_available(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/is_write_available function:");
return (this->_ev_list[index].filter == EVFILT_WRITE);
}
void webserv::Kqueue::test_error(int fd, const std::string &str)
{
if (fd < 0)
{
std::cerr << RED << str << " ";
perror("The following error occured: ");
std::cerr << RESET;
exit(EXIT_FAILURE);
}
}
/************************ GETTERS/SETTERS ************************/
struct kevent *webserv::Kqueue::get_event_list()
{
return (this->_ev_list);
}
int webserv::Kqueue::get_fd(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/get_ev_list function:");
return (this->_ev_list[index].ident);
}
void webserv::Kqueue::set_kqueue(int fd)
{
this->_kq = fd;
}

How would I define move constructor and move assignment operator for unique_ptr of custom data type?

class threadMsg_t {
private:
string msg;
int type;
public:
threadMsg_t(const string& msg, int type) : msg(msg), type(type) {};
threadMsg_t& operator=(threadMsg_t&& oldMsg)
{
msg = move(oldMsg.msg);
type = move(oldMsg.type);
return *this;
}
threadMsg_t(threadMsg_t&& oldMsg) {
msg = move(oldMsg.msg);
type = move(oldMsg.type);
}
int getType() { return type; }
string getMsg() { return msg; }
};
using msgP_t = unique_ptr<threadMsg_t>;
static queue<msgP_t> q;
static condition_variable cv;
static mutex mtx;
static void postMsg(threadMsg_t* newMsg)
{
unique_lock<mutex> lck(mtx);
q.push(std::move(msgP_t{newMsg}));
cv.notify_one();
}
class workerThread_t {
public:
static void processMsg()
{
while(true) {
unique_lock<mutex> lck{mtx};
if(q.empty()) {
cout << "Waiting for the message!" << endl;
cv.wait(lck, []() { return !(q).empty(); });
}
if(q.empty()) {
continue;
}
auto msgP = move(q.front());
threadMsg_t* msg = msgP.get();
q.pop();
cout << "Processed Message - " << msg->getMsg() << endl;
lck.unlock();
}
}
thread* getThread()
{
return m_workerThread;
}
workerThread_t() {
m_workerThread = new thread(&processMsg);
}
~workerThread_t()
{
delete(m_workerThread);
}
private:
thread* m_workerThread;
};
Code works fine. But wondering the behavior when I do move(unique_ptr object) inside postMsg(). Seems like its not invoking the move constructor defined. Not sure whether its possible to define constructor for unique_ptr. I know that its needed for a custom structure containing "string" and "int". How would it behave if I have a ptr inside the structure?

C++11 condtional variable

I am trying make a lot of mistakes to learn Concurrency in C++11. I have to ask this,
Here is what this one is supposed to do:
One queue, and three threads, one is suppose to put an integer into the queue, the other twos are suppose to correspondingly increase s1, s2 by popping the queue so that I can get total sum of numbers that were in the queue. To make it simpler I put 1 through 10 numbers into the queue.
But sometimes it works and sometimes it seems like there is an infinite loop:: what would be the reason?
#include <queue>
#include <memory>
#include <mutex>
#include <thread>
#include <iostream>
#include <condition_variable>
#include <string>
class threadsafe_queue {
private:
mutable std::mutex mut;
std::queue<int> data_queue;
std::condition_variable data_cond;
std::string log; //just to see what is going on behind
bool done;
public:
threadsafe_queue(){
log = "initializing queue\n";
done = false;
}
threadsafe_queue(threadsafe_queue const& other) {
std::lock_guard<std::mutex> lk(other.mut);
data_queue = other.data_queue;
}
void set_done(bool const s) {
std::lock_guard<std::mutex> lk(mut);
done = s;
}
bool get_done() {
std::lock_guard<std::mutex> lk(mut);
return done;
}
void push(int new_value) {
std::lock_guard<std::mutex> lk(mut);
log += "+pushing " + std::to_string(new_value) + "\n";
data_queue.push(new_value);
data_cond.notify_one();
}
void wait_and_pop(int& value) {
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk, [this]{return !data_queue.empty();});
value = data_queue.front();
log += "-poping " + std::to_string(value) + "\n";
data_queue.pop();
}
std::shared_ptr<int> wait_and_pop() {
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk, [this]{return !data_queue.empty();});
std::shared_ptr<int> res(std::make_shared<int>(data_queue.front()));
log += "- popping " + std::to_string(*res) + "\n";
data_queue.pop();
return res;
}
bool try_pop(int& value) {
std::lock_guard<std::mutex> lk(mut);
if (data_queue.empty()) {
log += "tried to pop but it was empty\n";
return false;
}
value = data_queue.front();
log += "-popping " + std::to_string(value) + "\n";
data_queue.pop();
return true;
}
std::shared_ptr<int> try_pop() {
std::lock_guard<std::mutex> lk(mut);
if (data_queue.empty()) {
log += "tried to pop but it was empty\n";
return std::shared_ptr<int>();
}
std::shared_ptr<int> res(std::make_shared<int>(data_queue.front()));
log += "-popping " + std::to_string(*res) + "\n";
data_queue.pop();
return res;
}
bool empty() const {
std::lock_guard<std::mutex> lk(mut);
//log += "checking the queue if it is empty\n";
return data_queue.empty();
}
std::string get_log() {
return log;
}
};
threadsafe_queue tq;
int s1, s2;
void prepare() {
for (int i = 1; i <= 10; i++)
tq.push(i);
tq.set_done(true);
}
void p1() {
while (true) {
int data;
tq.wait_and_pop(data);
s1 += data;
if (tq.get_done() && tq.empty()) break;
}
}
void p2() {
while (true) {
int data;
tq.wait_and_pop(data);
s2 += data;
if (tq.get_done() && tq.empty()) break;
}
}
int main(int argc, char *argv[]) {
std::thread pp(prepare);
std::thread worker(p1);
std::thread worker2(p2);
pp.join();
worker.join();
worker2.join();
std::cout << tq.get_log() << std::endl;
std::cout << s1 << " " << s2 << std::endl;
return 0;
}
Look at function p1 line 5
if (tq.get_done() && tq.empty()) break;
So you checked the queue if it was empty. It was not. Now you loop and enter
tq.wait_and_pop(data);
where you'll find
data_cond.wait(lk, [this]{return !data_queue.empty();});
which is essentially
while (data_queue.empty()) {
wait(lk);
}
notice the missing '!'.
Now your thread sits there and waits for the queue not to be empty, which will never happen, because the producer id done filling the queue. The thread will never join.
There are many ways to fix this. I'm sure you'll find one on your own.

Bluetooth thread 'Bad file descriptor' in recv funktion

I am writing a server/client program using linux sockets. I want that both server and client can read and write at the same time with threads.
(The full code I followed can be downloaded at http://www.praxisbuch.net/embedded-linux/downloads.html).
When I start() my thread it throws a infinite loop of 'Bad file descriptor'.
My client.cpp is as follows:
class receiveThread : public Thread {
public:
receiveThread(RawMessage& rawMsg) : data_control(rawMsg) {}
virtual void run() {
cout << "starting recveive thread ..." << endl;
while(1) {
int recvBytes = bt_socket.recieveMessage(&temp_data_control);
try {
cout << "Received new Target Position: " << temp_data_control.data.value1 << endl;
data_control = temp_data_control;
}
catch (SocketException) {
cout << "Received exception " << endl;
sleep(1);
}
}
}
~receiveThread() {
bt_socket.disconnect();
}
private:
BtSocket bt_socket;
RawMessage temp_data_control;
RawMessage& data_control;
};
int main() {
BtSocket BtClient(PORTNUM);
// connect to the server.
BtClient.connectToServer();
RawMessage raw_mes;
receiveThread recv_thread(raw_mes);
recv_thread.start(); //the error occurs
while (1)
{
//do something
}
return 0;
}
thread.cpp is as follows:
void Thread::start() throw(Thread::Exception) {
if (pthread_create(&thread_id, 0, thread_starter, (void *) this) != 0) {
throw Exception("Thread::start: Cannot create thread");
}
}
void* Thread::thread_starter(void* thread_obj) {
Thread* self = reinterpret_cast<Thread*> (thread_obj);
self->setRunning(true);
self->run();
self->setRunning(false);
return 0;
}
In socket.cpp the exception is thrown:
int BtSocket::recieveMessage(AbstractDatagram *abstractDgm)
{
int numBytes;
if ((numBytes = recv(s, abstractDgm->getData(), abstractDgm->getSize(), 0)) < 0)
{
cout << strerror(errno) << endl;
}
return numBytes;
}
I really don't know what the problem is.
Any help would be extremely appreciated!
EDIT: (also from socket.cpp)
Socket::Socket(int pNumber)
{
portNumber = pNumber;
blocking = 1;
if ((s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) == -1)
{
throw SocketException("socket failed (socket())", true);
}
locAddr.rc_family = AF_BLUETOOTH;
str2ba(dest, &locAddr.rc_bdaddr);
locAddr.rc_channel = portNumber;
}
void BtSocket::connectToServer()
{
struct sockaddr_rc serverAddr;
serverAddr.rc_family = AF_BLUETOOTH;
serverAddr.rc_channel = 1;
str2ba(dest, &serverAddr.rc_bdaddr);
if (connect(s, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1)
{
throw SocketException("Connect failed (connect())", true);
}
}
I think I opend the socket correctly!?
Could it have been closed somehow?

Qt MainWindow is not updating

I am using Qt to generate a Window. Additionally I use libnfc to get access to a nfc reader, so far so good.
In my self written nfc-class i generate a new thread, this thread is polling for new tags on the reader. If there is a new tag, the thread will start a signal event for the MainWindow.
In the main window I have just a QWebView which will show different websites on different states (after start, new tag, tag removed), just realy basic stuff.
My problem is now: that the main window (or the QWebView) is not updating. If i switch to another programm and go back to my app, the window will be updated. I was already searching with google and trying different stuff but nothing helps.
Here the thread code:
class NFC_Thread : public QThread
{
Q_OBJECT
public:
NFC_Thread(NFC_Reader * Reader);
void run();
signals:
void NewTarget(nfc_target Target);
void TargetRemoved(nfc_target Target);
private:
int mError;
bool mStopPolling;
};
void NFC_Thread::run()
{
mError = 0;
mStopPolling = false;
while(!mStopPolling)
{
nfc_target Target;
mError = nfc_initiator_poll_target(mReader->GetDevice(), nmModulations, szModulations, mPollNr, mPollPeriod, &Target);
if(mError > 0)
{
cout << "NFC: found target" << endl;
}
#warning Bug in driver: Timeout generate a NFC_EIO Error, 'https://code.google.com/p/libnfc/issues/detail?id=224'
else if(mError > 0)
{
cout << "NFC: Error" << endl;
mStopPolling = true;
}
else
{
cout << "NFC: no target found" << endl;
}
}
}
MainWindow Code:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void SetNewTarget(nfc_target Target);
void doTargetRemoved(nfc_target Target);
private:
bool event(QEvent *event);
void resizeEvent(QResizeEvent *);
void adjust();
Ui::MainWindow *ui;
QWebView * mWebView;
};
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
mWebView = new QWebView(this);
mWebView->load(QUrl("http://www.pbuchegger.at/"));
mWebView->show();
}
void MainWindow::SetNewTarget(nfc_target Target)
{
QString str = "NEW TARGET: \n";
{
char * s;
str_nfc_target(&s, Target, false);
str += s;
delete s;
}
//cout << "NFC: Target: " << str << endl;
mWebView->load(QUrl("http://www.google.at"));
update();
repaint();
mWebView->update();
qApp->processEvents();
/*QMessageBox msgBox;
msgBox.setText(str);
msgBox.exec();*/
}
void MainWindow::doTargetRemoved(nfc_target Target)
{
QString str = "TARGET REMOVED: \n";
{
char * s;
str_nfc_target(&s, Target, false);
str += s;
delete s;
}
//cout << "NFC: Target: " << str << endl;
mWebView->load(QUrl("http://www.cde.at"));
update();
repaint();
mWebView->update();
qApp->processEvents();
/*QMessageBox msgBox;
msgBox.setText(str);
msgBox.exec();*/
}
bool MainWindow::event(QEvent *event)
{
if(event->type() == QEvent::Resize)
{
adjust();
return true;
}
return false;
}
void MainWindow::resizeEvent(QResizeEvent *)
{
adjust();
}
void MainWindow::adjust()
{
mWebView->setGeometry(0, 0, ui->centralWidget->geometry().width(), ui->centralWidget->geometry().height());
}
main code:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qRegisterMetaType<nfc_target>("nfc_target");
MainWindow w;
w.setWindowState(Qt::WindowMaximized);
NFC_Reader Reader;
nfc_device_string devs;
size_t nr;
QString str = "";
Reader.GetDevices(devs, nr);
if(nr > 0)
{
if(!Reader.InitReader(NULL))
{
str += "Error on init!";
}
else
{
Reader.Start_Polling();
str += "Started Polling!";
}
}
else
{
str += "No Device found!";
}
w.SetText(str);
SignalHelper Helper;
QObject::connect(Reader.GetThread(), SIGNAL(NewTarget(nfc_target)), &Helper, SLOT(doNewTarget(nfc_target)));
QObject::connect(Reader.GetThread(), SIGNAL(TargetRemoved(nfc_target)), &Helper, SLOT(doTargetRemoved(nfc_target)));
QObject::connect(&Helper, SIGNAL(NewTarget(nfc_target)), &w, SLOT(SetNewTarget(nfc_target)));
QObject::connect(&Helper, SIGNAL(TargetRemoved(nfc_target)), &w, SLOT(doTargetRemoved(nfc_target)));
w.show();
int ret = a.exec();
Reader.Abort_Polling();
return ret;
}
As u can see, I have a "Helper" class, this class is just getting the signal in a slot and starting again a signal which will be forward to the mainwindow. If i want to forward the signal directly to the mainwindow, nothing is happening (like the signal is not fired), but i was checking it with the Qt-About box, and the box is showing up.
Helper class:
class SignalHelper : public QObject
{
Q_OBJECT
public slots:
void doNewTarget(nfc_target Target);
void doTargetRemoved(nfc_target Target);
signals:
void NewTarget(nfc_target Target);
void TargetRemoved(nfc_target Target);
};
void SignalHelper::doNewTarget(nfc_target Target)
{
emit NewTarget(Target);
}
void SignalHelper::doTargetRemoved(nfc_target Target)
{
emit TargetRemoved(Target);
}
no compiler errors or linker errors. this code shows just the important stuff, all the unimportant stuff is removed. just for your information the project file:
QT += core gui testlib
QT += webkit
greaterThan(QT_MAJOR_VERSION, 4) {
QT += widgets
}
TARGET = NFC_GUI
TEMPLATE = app
SOURCES += main.cpp \
mainwindow.cpp \
nfc_thread.cpp \
nfc_reader.cpp \
signal_helper.cpp
HEADERS += mainwindow.h nfc_thread.h nfc_reader.h signal_helper.h
FORMS += mainwindow.ui
LIBS += -lnfc
Making my comment an answer:
Your function
bool MainWindow::event(QEvent *event)
{
if(event->type() == QEvent::Resize)
{
adjust();
return true;
}
return false;
}
eats any event which is handled in QMainWindow except for QEvent::Resize. You need to call the default behaviour for events you are not interested in:
bool MainWindow::event(QEvent *event)
{
if(event->type() == QEvent::Resize)
{
adjust();
return true;
}
// call the parent implementation
return QMainWindow::event(event);
}
Note you can also just simply implement QWidget::resizeEvent:
void MainWindow::resizeEvent(QResizeEvent *event)
{
adjust();
QMainWindow::resizeEvent(event);
}
If you're calling slots from signals between different threads, you need to make the connect calls with Qt::QueuedConnection as the Connection Type.

Resources