C++ app.exec()无法调用其他方法(静态库)

C++ app.exec()无法调用其他方法(静态库),c++,qt,C++,Qt,我创建了一个静态库。我需要通过调用一些方法来改变图片的位置。问题是“app.exec()”完全阻塞了进程。你知道怎么做吗 非常感谢 这是我的lib头文件 int init(int argc, char *argv[], int width, int height); void changePos (int x, int y); void destroyPic(); 我的初衷是: QWidget*窗口(0); QLabel*pic(0) 问题是我无法在我的主代码(使用此库)中调用方法change

我创建了一个静态库。我需要通过调用一些方法来改变图片的位置。问题是“app.exec()”完全阻塞了进程。你知道怎么做吗

非常感谢

这是我的lib头文件

int init(int argc, char *argv[], int width, int height);
void changePos (int x, int y);
void destroyPic();
我的初衷是: QWidget*窗口(0); QLabel*pic(0)

问题是我无法在我的主代码(使用此库)中调用方法changePos或destroy,因为app.exec()会阻止进程。。。怎么做

非常感谢

在使用QApplication::exec()进入QApplication事件循环之前,可以调用init()

我能想到的唯一其他选择是:

  • Lazy init,当库的用户调用changePos()或destroyPic()时,如果尚未调用它,则调用init()

  • 使用单次触发计时器在事件循环后执行:

  • 比如:

    QTimer::singleShot(0, this, SLOT(init()));
    

    这需要您有一个QObject,并且init或其他调用init的函数需要很多。在QApplication::exec()之前调用此函数,插槽将在事件循环启动后执行。

    您需要在单独的QThread中启动QApplication。这在下面的代码中显示。我还没有让它在OSX上运行,但我相信它应该是可行的。我需要先为OSX做一个调试构建,然后看看有什么进展。经过测试,它可以在Windows上工作,并且可能也可以在X11上工作。目标C代码仅适用于mac,它可能是必需的,但还不够

    它是一个完整的可运行应用程序,对于一个库,您可以删除
    main()
    函数并调用init、changePos,然后根据需要直接完成

    #applib.pro
    QT       += core gui
    TARGET = applib
    TEMPLATE = app
    !x11:!embedded:!qpa:mac {
        LIBS_PRIVATE += -framework Cocoa -lz
        OBJECTIVE_SOURCES += thread.mm
    }
    SOURCES += main.cpp
    
    //main.cpp
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    //
    //原料药
    //
    外部“C”{
    void init(int argc,字符**argv);
    无效更改位置(整数x,整数y);
    空隙饰面();
    }
    //演示代码,从库中删除
    int main(int argc,字符**argv)
    {
    类帮助程序:私有QThread{
    公众:
    静态void msleep(无符号长ms){
    QThread::msleep(ms);
    }
    };
    初始值(argc,argv);
    助手:msleep(2000);
    changePos(0,0);
    助手:msleep(2000);
    完成();
    }
    //
    //实施
    //
    结构PosEvent:publicqevent
    {
    PosEvent(intx,inty):QEvent(t()),
    x(x_),y(y_){
    常数int x,y;
    静态QEvent::Type t(){return(QEvent::Type)(QEvent::User+0);}
    };
    类小部件:公共QLabel
    {
    公众:
    Widget():QLabel(“你好!”){}
    受保护的:
    无效自定义事件(QEvent*ev){
    如果(ev->type()==PosEvent::t()){
    PosEvent*pev=静态_铸造(ev);
    移动(pev->x,pev->y);
    }
    }
    };
    类QCoreApplicationPrivate{
    公众:
    静态QThread*主线程;
    };
    外部“C++”{Qt::HANDLE Qt_应用程序_线程_id;}
    类AppThread:publicQThread
    {
    公众:
    AppThread(int&argc,char**argv){
    Q_断言(!实例);
    实例=此;
    QMutexLocker锁(&argMutex);
    argc=&argc;
    argv=argv_389;;
    start();
    wc.wait(&argMutex);
    }
    静态无效更改位置(整数x,整数y){
    QCoreApplication::postEvent(实例->小部件,新的PosEvent(x,y));
    }
    静态空隙饰面(){
    实例->应用->退出();
    实例->等待();
    删除实例;
    }
    受保护的:
    无效运行(){
    int i=0;
    #ifdef Q_OS_UNIX
    //qDebug(“%p”,qt\u应用程序\u线程\u id);
    QCoreApplicationPrivate::theMainThread=QThread::currentThread();
    #恩迪夫
    申请a(i,0);
    app=&a;
    wc.wakeAll();
    小部件w;
    widget=&w;
    w、 show();
    rc=a.exec();
    }
    私人:
    静态AppThread*实例;
    QCoreApplication*app;
    QObject*小部件;
    QMutex argMutex;
    qwaitconditionwc;
    int*argc;
    字符**argv;
    int rc;
    };
    AppThread*AppThread::instance=0;
    bool多线程();
    #ifndef Q_OS_MAC
    bool多线程(){return true;}
    #恩迪夫
    外部“C”void init(内部argc,字符**argv){
    多线程();
    #ifdef Q_OS_MAC
    qDebug(“DYLD\u图像后缀=%s”,getenv(“DYLD\u图像后缀”);
    #恩迪夫
    新的AppThread(argc、argv);
    }
    外部“C”void changePos(intx,inty){AppThread::changePos(x,y);}
    外部“C”void finish(){AppThread::finish();}
    
    //thread.mm
    #进口
    @接口死线程:NSObject{;;}
    +(void)输入多线程模式;
    +(void)清空读取方法:(id)obj;
    @结束
    @实现死线程
    +(无效)输入多线程模式{
    NSAutoreleasePool*池=[[NSAutoreleasePool alloc]init];
    [NSThread detachNewThreadSelector:@selector(emptyThreadMethod:)
    toTarget:[DeadThread类]和对象:nil];
    [池释放];
    }
    +(void)emptyThreadMethod:(id)obj{(void)obj;}
    @结束
    bool多线程()
    {
    [死线程进入多线程模式];
    返回[NSThread isMultiThreaded];
    }
    
    事实上,我知道app.exec()是一个阻塞函数,我想知道如何在不使用此函数的情况下显示窗口,或者如何在不阻塞我的程序的情况下显示窗口。看起来您的静态库实际上是一个程序。。。你想再做什么?我有一个不使用QT的程序。我只是在里面添加了Qt库。因为这个程序的一部分需要显示一个窗口,带有一些图片,移动这个图片,然后“销毁”这个窗口,我想使用一个lib来显示窗口,图片,移动它们,然后销毁它们,而不在我的主程序中添加Qt(带有qmake,等等)(因为这很复杂,我真的不想在我的主程序中包括Qt)在这种情况下,你需要在一个新的进程中启动Qt,你的意思是在线程中启动init方法,对吗?
    #applib.pro
    QT       += core gui
    TARGET = applib
    TEMPLATE = app
    !x11:!embedded:!qpa:mac {
        LIBS_PRIVATE += -framework Cocoa -lz
        OBJECTIVE_SOURCES += thread.mm
    }
    SOURCES += main.cpp
    
    //main.cpp
    #include <cstdlib>
    #include <QtCore/QThread>
    #include <QtCore/QMutex>
    #include <QtCore/QMutexLocker>
    #include <QtCore/QWaitCondition>
    #include <QtCore/QEvent>
    #include <QtGui/QLabel>
    #include <QtGui/QApplication>
    
    //
    // API
    //
    
    extern "C" {
        void init(int argc, char ** argv);
        void changePos(int x, int y);
        void finish();
    }
    
    // demonstration code, remove from the library
    int main(int argc, char ** argv)
    {
        class Helper : private QThread {
        public:
            static void msleep(unsigned long ms) {
                QThread::msleep(ms);
            }
        };
    
        init(argc, argv);
        Helper::msleep(2000);
        changePos(0, 0);
        Helper::msleep(2000);
        finish();
    }
    
    //
    // IMPLEMENTATION
    //
    
    struct PosEvent : public QEvent
    {
        PosEvent(int x_, int y_) : QEvent(t()),
            x(x_), y(y_) {}
        const int x, y;
        static QEvent::Type t() { return (QEvent::Type)(QEvent::User + 0); }
    };
    
    class Widget : public QLabel
    {
    public:
        Widget() : QLabel("Hello!") {}
    protected:
        void customEvent(QEvent * ev) {
            if (ev->type() == PosEvent::t()) {
                PosEvent * pev = static_cast<PosEvent*>(ev);
                move(pev->x, pev->y);
            }
        }
    };
    
    class QCoreApplicationPrivate {
    public:
        static QThread * theMainThread;
    };
    
    extern "C++" { Qt::HANDLE qt_application_thread_id; }
    
    class AppThread : public QThread
    {
    public:
        AppThread(int& argc_, char ** argv_) {
            Q_ASSERT(!instance);
            instance = this;
            QMutexLocker lock(&argMutex);
            argc = &argc_;
            argv = argv_;
            start();
            wc.wait(&argMutex);
        }
        static void changePos(int x, int y) {
            QCoreApplication::postEvent(instance->widget, new PosEvent(x,y));
        }
        static void finish() {
            instance->app->exit();
            instance->wait();
            delete instance;
        }
    
    protected:
        void run() {
    
            int i = 0;
    
    #ifdef Q_OS_UNIX
            //qDebug("%p", qt_application_thread_id);
            QCoreApplicationPrivate::theMainThread = QThread::currentThread();
    #endif
            QApplication a(i, 0);
            app = &a;
            wc.wakeAll();
    
            Widget w;
            widget = &w;
            w.show();
    
            rc = a.exec();
        }
    private:
        static AppThread * instance;
        QCoreApplication * app;
        QObject * widget;
        QMutex argMutex;
        QWaitCondition wc;
        int* argc;
        char** argv;
        int rc;
    
    };
    AppThread * AppThread::instance = 0;
    
    bool multiThreader();
    
    #ifndef Q_OS_MAC
    bool multiThreader() { return true; }
    #endif
    
    extern "C" void init(int argc, char ** argv) {
        multiThreader();
    #ifdef Q_OS_MAC
        qDebug("DYLD_IMAGE_SUFFIX=%s", getenv("DYLD_IMAGE_SUFFIX"));
    #endif
        new AppThread(argc, argv);
    }
    
    extern "C" void changePos(int x, int y) { AppThread::changePos(x, y); }
    
    extern "C" void finish() { AppThread::finish(); }
    
    //thread.mm
    #import <Foundation/Foundation.h>
    
    @interface DeadThread : NSObject { ;; }
        + (void)enterMultiThreadedMode;
        + (void)emptyThreadMethod:(id)obj;
    @end
    @implementation DeadThread
        + (void)enterMultiThreadedMode {
            NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
            [NSThread detachNewThreadSelector:@selector(emptyThreadMethod:)
                toTarget:[DeadThread class] withObject:nil];
            [pool release];
        }
    + (void)emptyThreadMethod:(id)obj { (void)obj; }
    @end
    
    bool multiThreader()
    {
        [DeadThread enterMultiThreadedMode];
        return [NSThread isMultiThreaded];
    }