레이블이 qt인 게시물을 표시합니다. 모든 게시물 표시
레이블이 qt인 게시물을 표시합니다. 모든 게시물 표시

2025년 7월 1일 화요일

Qt 리눅스 빌드

sudo apt-get install -y \

    libx11-xcb-dev \

    libxcb1-dev \

    libxcb-render0-dev \

    libxcb-shm0-dev \

    libxcb-keysyms1-dev \

    libxcb-image0-dev \

    libxcb-icccm4-dev \

    libxcb-sync-dev \

    libxcb-xfixes0-dev \

    libxcb-shape0-dev \

    libxcb-randr0-dev \

    libxcb-render-util0-dev \

    libxrender-dev \

    libxcb-xinerama0-dev


mkdir build && cd build


 ../configure \

    -platform linux-g++ \

    -prefix /home/kimdh/Qt-5.15.2 \

    -opensource \

    -confirm-license \

    -release \

    -gstreamer \

-opengl desktop \

    -optimized-qmake \

    -nomake tests \

    -nomake examples \

-skip qtandroidextras \

-skip qtconnectivity \

-skip qtwebchannel \

    -skip qtwebengine \

-skip qtwebsockets \

    -skip qtactiveqt \

    -skip qtandroidextras \

    -skip qtdatavis3d \

    -skip qtgamepad \

    -skip qtlocation \

    -skip qtlottie \

    -skip qtmacextras \

    -skip qtpurchasing \

    -skip qtremoteobjects \

    -skip qtscript \

    -skip qtwebglplugin \

    -skip qtwebview \

    -skip qtspeech \

    -skip qtserialport \

    -skip qtserialbus    


make

make install


2022년 3월 21일 월요일

Qt QQueue 로 만든 간단한 template 기반 thread safe Queue 클래스

 #ifndef MYBUFFERQUEUE_H

#define MYBUFFERQUEUE_H

#include <QQueue>
#include <QMutexLocker>

template<typename T>
class MyBufferQueue
{
public:
    MyBufferQueue(int maxCount);
    virtual ~MyBufferQueue();

    int push(T *buffer);
    T* pop();

    void clear();
    int count();

private:
    QQueue<T*>      m_queue;
    QMutex          m_mutex;
    int             m_nMaxCount;
};

template <typename T>
MyBufferQueue<T>::MyBufferQueue(int maxCount)
{
    m_nMaxCount = maxCount;
}

template <typename T>
MyBufferQueue<T>::~MyBufferQueue()
{
    clear();
}

template <typename T>
int MyBufferQueue<T>::push(T *buffer)
{
    QMutexLocker locker(&m_mutex);

    if (m_nMaxCount > 0) {
        if (m_queue.count() >= m_nMaxCount)
            return -1;
    }

    m_queue.enqueue(buffer);

    return m_queue.count();
}

template <typename T>
T* MyBufferQueue<T>::pop()
{
    QMutexLocker locker(&m_mutex);

    T *image = NULL;
    if (!m_queue.isEmpty()) image = m_queue.dequeue();

    return image;
}

template <typename T>
void MyBufferQueue<T>::clear()
{
    QMutexLocker locker(&m_mutex);
    qDeleteAll(m_queue);
    m_queue.clear();
}

template <typename T>
int MyBufferQueue<T>::count()
{
    QMutexLocker locker(&m_mutex);
    return m_queue.count();
}

class AudioBuffer {
public:
    AudioBuffer() {
        data = NULL;
        size = 0;
    }

    AudioBuffer(char *_data, int _size) {
        data = new char[_size];
        memcpy(data, _data, _size);
        size = _size;
    }

    virtual ~AudioBuffer() {
        if (size > 0) delete[] data;
    }

public:
    char*   data;
    int     size;
};

#endif // MyBufferQueue_H




< 사용법 >

MyBufferQueue<AudioBuffer>*   m_pSendQue = new MyBufferQueue<AudioBuffer>(100);
...
AudioBuffer *pSendBuffer = new AudioBuffer(data, size);
m_pSendQue->push(pSendBuffer);
...
...
AudioBuffer* pBuffer = m_SendQue->pop();
...
delete pBuffer;

2021년 6월 14일 월요일

Qt QString section 함수를 활용한 path 체크 함수

경로 문자열을 입력하면 해당 경로를 자동 체크해서 없으면 경로생성해주는 함수

void checkPath(QString path)
{
    int i = 0;
    QString filepath = "";

    do
    {
        filepath = path.section('/', 0, i++);   // 섹션별 분할

        // 디렉토리 존재 여부 체크  없으면 생성
        QDir dir(filepath);
        if (!dir.exists()) {
            dir.mkdir(filepath);
        }

    } while (filepath != path);
}


checkPath("d:/aaa/bbb/ccc"); => 해당 경로에 디렉토리 없으면 각 디렉토리 자동생성

2020년 11월 16일 월요일

QT moveToThread 방식으로 쓰레드 생성시 QThread wait 함수 사용

 QThread 상속으로 쓰레드를 생성하지않고 QObject의 moveToThread 함수로 쓰레드를 생성할때 QThread의 wait 함수를 사용하면 무한 블러킹에 걸린다.

이때 

connect(worker, SIGNAL(finished()), thread, SLOT(quit()));

와 같은 방법으로 worker 에서 finished 를 emit 하고 thread 가 받아서 quit 하게 하여도 마찬가지로 wait 에서는 무한 블러킹에 걸린다

방법은 오직 thread->exit() 과 같이 QThread의 exit 함수를 호출하는 방법 밖에 없었다.

따라서 다음과 같이 구현하면 Worker 쓰레드가 종료할때까지 wait 할 수 있다.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QThread>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QThread *thread);
    virtual ~Worker();

public slots:
    void doWork();

private:
    QThread*    m_pThread;
};

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_btnStart_clicked();
    void on_btnWait_clicked();

private:
    Ui::MainWindow *ui;

    QThread*    m_pThread;
    Worker*     m_pWorker;
};
#endif // MAINWINDOW_H



#include "mainwindow.h"
#include "ui_mainwindow.h"

Worker::Worker(QThread *thread)
{
    m_pThread = thread;
}
Worker::~Worker()
{
}
void Worker::doWork()
{
    int count = 0;
    while (count++ < 10) {
        printf("do work\n");
        QThread::sleep(1);
    }

    m_pThread->exit();    // 인수로 받은 QThread의 exit을 호출해야 함
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_pThread = new QThread();
    m_pWorker = new Worker(m_pThread);
    m_pWorker->moveToThread(m_pThread);

    connect(m_pThread, SIGNAL(started()), m_pWorker, SLOT(doWork()));
}
MainWindow::~MainWindow()
{
    delete m_pThread;
    delete m_pWorker;
    delete ui;
}

void MainWindow::on_btnStart_clicked()
{
    if (m_pThread->isRunning()) {
        return;
    }

    m_pThread->start();
}

void MainWindow::on_btnWait_clicked()
{
    printf("wait start\n");
    m_pThread->wait();
    printf("wait finished\n");
}

위와 같이 Worker는 QThread를 인수로 받아서 쓰레드 종료시 exit() 을 호출하면 wait() 함수에서 
종료시점에 동기화를 맞출수 있다

2020년 9월 1일 화요일

QTcpSocket 외부 쓰레드에서 write 하는 방법

 QTcpSocket 은 생성된 쓰레드 외에 다른 쓰레드에서 write 를 시도할 경우 에러를 리턴하며 전송이 되지않는다. 이럴 경우 아래와 같이 이벤트를 발생시켜 생성 쓰레드에서 write 처리를 하도록해서 문제를 해결할 수 있다.


 #ifndef TCPAUDIOSENDER_H  
 #define TCPAUDIOSENDER_H  
 #include <QThread>  
 #include <QTcpServer>  
 #include <QTcpSocket>  
 #include <QMutex>  
 #include "logwriter.h"  
 #include "bufferqueue.h"  
 class TcpAudioSender : public QThread  
 {  
   Q_OBJECT  
 public:  
   explicit TcpAudioSender(BufferQueue<AudioBuffer> *pSendQue, QThread *parent = 0);  
   virtual ~TcpAudioSender();  
 signals:  
   void socketWriteEvent(QTcpSocket *sock, AudioBuffer *buffer);  
 public slots:  
   void onNewConnection();  
   void onSocketStateChanged(QAbstractSocket::SocketState socketState);  
   void onReadyRead();  
   void onSocketWrite(QTcpSocket *sock, AudioBuffer *buffer);  
 public:  
   bool startServer(int port);  
   void stopServer();  
 protected:  
   virtual void run() override;  
 protected:  
   bool      m_bRun;  
   QTcpServer*     m_pServer;  
   int         m_nPort;  
   QList<QTcpSocket*> m_clientList;  
   QMutex       m_clientListMutex;  
   BufferQueue<AudioBuffer>*  m_pSendQue;  
   LogWriter*   m_pLogWriter;  
 };  
 #endif // TCPAUDIOSENDER_H  



 #include "tcpaudiosender.h"  
 TcpAudioSender::TcpAudioSender(BufferQueue<AudioBuffer> *pSendQue, QThread *parent) : QThread(parent)  
 {  
   m_bRun = false;  
   m_pServer = new QTcpServer(this);  
   m_pSendQue = pSendQue;  
   m_pLogWriter = LogWriter::getInstance();  
 }  
 TcpAudioSender::~TcpAudioSender()  
 {  
   delete m_pServer;  
 }  
 bool TcpAudioSender::startServer(int port)  
 {  
   if (!m_pServer->listen(QHostAddress::Any, port)) {  
     m_pLogWriter->writeLog(QString("TcpAudioSender cannot open %1 port").arg(port));  
     return false;  
   }  
   m_nPort = port;  
   connect(m_pServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));  
   connect(this, SIGNAL(socketWriteEvent(QTcpSocket*, AudioBuffer*)), this, SLOT(onSocketWrite(QTcpSocket*, AudioBuffer*)));  
   m_bRun = true;  
   QThread::start();  
   return true;  
 }  
 void TcpAudioSender::stopServer()  
 {  
   m_pServer->close();  
   m_bRun = false;  
   QThread::wait();  
 }  
 void TcpAudioSender::onNewConnection()  
 {  
   QTcpSocket *clientSocket = m_pServer->nextPendingConnection();  
   connect(clientSocket, SIGNAL(readyRead()), this, SLOT(onReadyRead()));  
   connect(clientSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onSocketStateChanged(QAbstractSocket::SocketState)));  
   m_clientListMutex.lock();  
   m_clientList.push_back(clientSocket);  
   m_clientListMutex.unlock();  
 }  
 void TcpAudioSender::onSocketStateChanged(QAbstractSocket::SocketState socketState)  
 {  
   if (socketState == QAbstractSocket::UnconnectedState)  
   {  
     QTcpSocket* sender = static_cast<QTcpSocket*>(QObject::sender());  
     m_clientListMutex.lock();  
     m_clientList.removeOne(sender);  
     m_clientListMutex.unlock();  
   }  
 }  
 void TcpAudioSender::onReadyRead()  
 {  
   /*  
   QTcpSocket* sender = static_cast<QTcpSocket*>(QObject::sender());  
   QByteArray datas = sender->readAll();  
   for (QTcpSocket* socket : m_clientList) {  
     if (socket != sender)  
       socket->write(QByteArray::fromStdString(sender->peerAddress().toString().toStdString() + ": " + datas.toStdString()));  
   }  
   */  
 }  
 void TcpAudioSender::onSocketWrite(QTcpSocket *sock, AudioBuffer *buffer)  
 {  
   int res = sock->write(buffer->data, buffer->size);  
   if (res != buffer->size) {  
     qDebug() << QString("TcpAudioSender(%1) cannot send client : %2, %3").arg(m_nPort).arg(res).arg(buffer->size);  
   }  
   delete buffer;  
   //qDebug() << "TcpAudioSender send :" << size << "bytes";  
 }  
 void TcpAudioSender::run()  
 {  
   while (m_bRun)  
   {  
     AudioBuffer *buffer = m_pSendQue->pop();  
     if (!buffer) {  
       usleep(10);  
       continue;  
     }  
     m_clientListMutex.lock();  
     for (QTcpSocket* socket : m_clientList) {  
       AudioBuffer *sendBuffer = new AudioBuffer(buffer->data, buffer->size);  
       emit socketWriteEvent(socket, sendBuffer);  
     }  
     m_clientListMutex.unlock();  
     delete buffer;  
   }  
 }  


2020년 7월 22일 수요일

간단한 Qt Thread 사용법

< MyThread.h>

class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(QThread *parent = 0);
virtual ~MyThread();

void startThread();
void stopThread();

protected:
virtual void run();

signals:
void started();
void finished();

protected:
bool m_bRun;
}



< MyThread.cpp>

MyThread::MyThread(QThread *parent) : QThread(parent);
{
m_bRun = false;
}

MyThread::~MyThread()
{
}

void MyThread::startThread()
{
m_bRun = true;
QThread::start();
}

void MyThread::stopThread()
{
m_bRun = false;
QThread::wait();
}

void MyThread::run()
{
emit started();

while (m_bRun)
{
...
}

emit finished();
}

2019년 7월 2일 화요일

windeployqt 사용시 주의할 점

qt 배포용 파일들 담아주는 windeployqt 사용시 반드시 32/64 비트 확인할 것.
32비트 빌드는 32비트용 windeployqt 사용 => 32비트 qt dll 들 가져옴
64비트 빌드는 64비트용 windeployqt 사용 => 64비트 qt dll 들 가져옴
(QT 5.XX 32bit for Desktop / QT 5.XX 64bit for Desktop)