2012-06-15 38 views
8

Tôi phải khởi động GUI Qt từ dll hiển thị DLLStartDLLStop. Bình thường (.exe) cách tiếp cận trong chính như sau:Bắt đầu Qt GUI từ dll (trong chức năng DLLStart)

int main(int argc, char *argv[]) { 
    QApplication a(argc, argv); Dialog w; 
    w.show(); 
    return a.exec(); 
} 

Vấn đề là chặn a.exec() cuộc gọi, vì trong dll DLLStart cần phải trả lại ngay lập tức (xem dưới đây). Bất kỳ cách giải quyết nào cho vấn đề này? Lưu ý: Câu hỏi này đang chia sẻ một số điểm chung với "Adding a Qt GUI to a Dynamic Library", nhưng không trùng lặp chính xác.

/** start module */ 
int __stdcall DLLStart(void) { 
    .. 
    QApplication qaDll(ac, av); Dialog w; 
    w.show(); 
    qaDll.exec(); 
    return 0; // never reached 
} 

/** stop module */ 
void __stdcall DLLStop(void) { } 
+1

Không biết. Tôi chỉ có thể đề nghị bạn thích tại window_qt.cpp trong mã opencv.org. Nó sử dụng Qt để hiển thị một cửa sổ đơn với vòng lặp sự kiện riêng của nó như là một phần của một thư viện không phải Qt. –

+1

Có phải 'DllStart' được gọi từ' DllMain'? Hoặc được gọi từ quá trình gọi điện thoại? – Synxis

+0

@MB bất kỳ gợi ý nào trong đại diện (http://code.opencv.org/projects/opencv/repository) tệp này được đặt. Tìm kiếm không tìm thấy nó, sẽ có một loot ở đó. –

Trả lời

12

Một cách hoạt động trên Windows là bắt đầu QApplication trong một riêng biệt QThread. Nó không di động - nó không hoạt động trên OS X (Tôi đang nghiên cứu một bản sửa lỗi).

Nhưng, bạn không cần một chuỗi riêng biệt. Nếu bạn tiêm mã của bạn vào một ứng dụng đang chạy, nó đã có một vòng lặp sự kiện. Bạn chỉ cần tạo đối tượng QApplication toàn cầu và bạn đã hoàn tất. Vòng lặp sự kiện đã chạy, vì vậy bạn không cần phải gọi số exec(). Các cửa sổ của Qt tích hợp với vòng lặp sự kiện gốc và mọi thứ đều tốt trên mặt trận đó.

Bạn do need để gọi QCoreApplication::processEvents một lần. Nó sẽ tích hợp cá thể ứng dụng hiện tại vào vòng lặp sự kiện cửa sổ, và đó là nó.

Do đó, mã khởi động của bạn có thể nhìn như sau:

int * argc = nullptr; 
char ** argv = nullptr; 
QApplication * app = nullptr; 
MainWindow * win = nullptr; 

static void startup() { 
    argc = new int(1); 
    argv = new char*[1]; 
    argv[0] = strdup("dummy"); 
    auto app = new QApplication(*argc, argv); 
    auto w = new MainWindow; 
    w->show(); 
    app->processEvents(); 
} 

static void shutdown() 
{ 
    delete win; 
    delete app; 
    free argv[0]; 
    delete [] argv; 
    delete argc; 
} 

Các startup()shutdown() nên được gọi là vào những thời điểm thích hợp (trên quá trình đính kèm và tách).


Câu trả lời cũ sau. Điều này không hoàn toàn cập nhật nữa.

Ví dụ ngắn dưới đây, để có ví dụ hoàn chỉnh khép kín, hãy xem other answer của tôi.

Nó không phải là di động và đó là lý do tại sao tài liệu Qt khuyên chống lại nó. Nó hoạt động tốt trên Windows. Chủ đề chính không phải là phép thuật - không phải trên Windows. Ca cao trên OS X là vụng về trong một cách và làm cho nó không thể, rõ ràng: (

Lưu ý rằng nếu ứng dụng tải DLL đã sử dụng Qt, thì không có gì thêm cho bạn để làm. cùng trình biên dịch C++, liên kết với cùng thời gian chạy C++ và sử dụng phiên bản Qt tương thích nhị phân với phiên bản được sử dụng bởi ứng dụng, sau đó bạn không cần bản sao của riêng mình là QApplication. hoặc khởi tạo một số QObjects với bộ hẹn giờ sẽ khiến chúng bận rộn.Bạn cũng có thể sử dụng QMetaObject::invokeMethod(obj, "mySlot", Qt::QueuedConnection) thay vì sử dụng bộ hẹn giờ: cuộc gọi sẽ được thực hiện khi điều khiển quay trở lại vòng lặp sự kiện. tùy chọn. rks tốt, như xa như tôi có thể nói.

Lưu ý rằng tôi hơi mỉa mai ở đây: Các điều kiện trong đoạn trước sẽ được đáp ứng đáng tin cậy nếu bạn là tác giả của ứng dụng sử dụng DLL. Nếu không - hãy quên nó đi.

class AppThread : public QThread { 
    int & argc; 
    char ** argv; 
    int result; 
    void run() { 
    QApplication a(argc, argv); 
    Dialog d; 
    d.show(); 
    result = a.exec(); 
    } 
public: 
    AppThread(int & argc_, char ** argv_) : argc(argc_), argv(argv_) {} 
} 

int __stdcall DLLStart(void) { 
    AppThread * thread = new AppThread(argc, argv); 
    thread->start(); 
    return 0; 
} 

void __stdcall DLLStop(void) { 
    qApp->thread()->quit(); 
    qApp->thread()->wait(); 
} 
+0

Sẽ kiểm tra cái này, cảm ơn cho đến nay! –

+0

Ứng dụng có thực sự hoạt động không? http://doc.qt.nokia.com/4.7-snapshot/thread-basics.html#gui-thread-and-worker-thread nói rằng bạn không thể có tiện ích trong chuỗi không phải là chính, mặc dù tôi không biết làm thế nào ứng xử nếu ứng dụng chính của bạn không xác định 'QApplication'. Và nếu ứng dụng chính, hoặc một số lib khác đã sử dụng qt thì sao? –

+0

Không có vấn đề gì khi có nhiều phiên bản QApplication miễn là chúng bị cô lập, sẽ xảy ra nếu bạn có nhiều luồng, mỗi luồng cho mỗi mô-đun nhị phân (DLL hoặc EXE), mỗi bản có hiệu lực Qt riêng. Các "ứng dụng chính" không phải là đặc biệt trong bất kỳ cách nào, nó chỉ là một mô-đun nhị phân hơn trong không gian địa chỉ của quá trình chạy. Nếu DLL của bạn không liên kết với cùng một thể hiện của Qt như EXE, thì nó sẽ ổn. Thông thường DLL của bạn sẽ là một DLL C, và bạn thậm chí sẽ không được đảm bảo để liên kết đến cùng một thời gian chạy C++. Heck, bạn thậm chí không thể đảm bảo EXE và DLL bằng cách sử dụng trình biên dịch C++ tương thích với ABI. –

Các vấn đề liên quan