Results 1 to 18 of 18

Thread: Access a COM object from a 3rd party dll across threads

  1. #1
    Join Date
    Sep 2010
    Posts
    6
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Default Access a COM object from a 3rd party dll across threads

    Hi!

    I've been around here for quite a while now and found a lot of time saving hints. Thanks a lot!

    For the problem I stumbled upon 2 days ago I did not find any suitable hint so any help is greatly appreciated.

    Roughly speaking, I developed a multithreaded application that converts some data into a predefined format. Now I have to add another input format that is delievered in form a dll packed API.

    When I put something like
    Qt Code:
    1. QAxObject *myObj = new QAxObject();
    2. myObj->setControl(CLASS_ID_OF_DLL);
    To copy to clipboard, switch view to plain text mode 
    somewhere in the main thread everything works fine and I can access the documented methods of the COM Object via dynamicCall(). But the same code in the process() method of another thread will lead to this error message:
    Qt Code:
    1. QAxBase::setControl: requested control {....} could not be instantiated.
    To copy to clipboard, switch view to plain text mode 
    I can't find anything if it is simply not possible to call a COM object from different threads simultaneously or if I'm just to blind to see the solution.

    Thanks in advance
    Dean

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Access a COM object from a 3rd party dll across threads

    QAxObject is a QObject subclass and as such cannot be used accross threads.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Sep 2010
    Posts
    6
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Default Re: Access a COM object from a 3rd party dll across threads

    Ok, this means I should able to create one individual QAxObject in each thread and access the dll but that results in the error listed above.

    The library provides a 3rd party interface for accessing a propriatary file format and is needed by each converter thread that operates on his own file.

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Access a COM object from a 3rd party dll across threads

    Have the COM objects live in one thread that acts as a server for other threads. You can use signals and slots to communicate between threads, just don't call the COM wrapper directly.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Sep 2010
    Posts
    6
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Default Re: Access a COM object from a 3rd party dll across threads

    That would be a nice idea. Unfortunatly this will not work because the processing of one image takes too long for sharing the COM object (it is blocked during the processing because it holds a lock on the current image).

    Is it definitely impossible to create two QAxObjects on one COM object at the same time from different threads?

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Access a COM object from a 3rd party dll across threads

    Is it definitely impossible to create two QAxObjects on one COM object at the same time from different threads?
    I don't know that. But if the com object is blocked, you won't be able to process more than one request at the same time anyway.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. #7
    Join Date
    Sep 2010
    Posts
    6
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Default Re: Access a COM object from a 3rd party dll across threads

    Well, it's not technically blocked. An ID representing the currently processed file is assigned to the COM object and only released after the processing has finished. Therefore more than one object is needed for parallel processing or otherwise I'm working two times on the same image.

    Thank you for your hints so far, but the error from my first post is still persisting.

  8. #8
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Access a COM object from a 3rd party dll across threads

    Perhaps instead of doing multi threading you could use multi processing and communicate using IPC. This would solve your problem as each object would be in a different process space.

  9. #9
    Join Date
    Sep 2010
    Posts
    6
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Default Re: Access a COM object from a 3rd party dll across threads

    Till now different importers work together fine using multitasking. I just read through QProcess and IPC roughly but I will give it a try when I'm back in the office tomorrow. Thanks.

  10. #10
    Join Date
    Sep 2010
    Posts
    6
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Default Re: Access a COM object from a 3rd party dll across threads

    Thanks for your advices so far.

    I digged into this thing a little bit further and stumbled across a really strange behaviour. For now I'm able to instantiate my QAxObject in a new thread. But only if accessed it from the main thread before.

    The following code works fine but commenting out test() in main() will deliver an error that the control could not be instantiated. I'm getting a little confused now, since I can't find anything about that in the docs. Could someone please lead me in the right direction?

    Qt Code:
    1. class MyThread : public QThread {
    2. public:
    3. MyThread(QObject *parent = 0);
    4.  
    5. protected:
    6. void run();
    7.  
    8. private:
    9. void process();
    10. };
    11.  
    12. MyThread::MyThread(QObject *parent) : QThread(parent) {
    13. moveToThread(this);
    14. }
    15.  
    16. void MyThread::process() {
    17. qDebug() << thread() << "accessing";
    18. QAxObject *comObj = new QAxObject();
    19. comObj->setControl("{CLASSID_HERE}");
    20. ::CoInitialize(comObj);
    21. }
    22.  
    23. void MyThread::run() {
    24. process();
    25. }
    26.  
    27.  
    28.  
    29. void test() {
    30. QAxObject *comObj = new QAxObject();
    31. qDebug() << qApp->thread() << "accessing";
    32. comObj->setControl("{CLASSID_HERE}");
    33. CoInitialize(comObj);
    34.  
    35. QVariantList params = QVariantList();
    36. params.append("D:\\path\\to\\file");
    37. comObj->dynamicCall("openFile(QString)", params);
    38.  
    39. delete comObj;
    40. }
    41.  
    42. int main(int argc, char* argv[]) {
    43. QApplication a(argc, argv);
    44.  
    45. test();
    46.  
    47. MyThread *mt = new MyThread();
    48. mt->start();
    49.  
    50. return a.exec();
    51. }
    To copy to clipboard, switch view to plain text mode 

  11. #11
    Join Date
    Mar 2010
    Location
    Capelle aan den IJssel, Netherlands
    Posts
    24
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows Symbian S60

    Default Re: Access a COM object from a 3rd party dll across threads

    I don't know if this still needs answering, but I stumbled upon this, looking for some answers myself.

    The reason your code does not work, when not calling test, is because you are calling CoInitialize in there.
    I think you misinterpreted what this function does, as you are passing your com object pointer.

    To use COM, you need to initialize it, using CoInitialize. The pointer parameter is a reserved parameter and you should not pass anything in it.
    But it still needs to be called, before creating a COM object (so before ->setControl), else it will fail. So I am guessing, the comObj->setControl in your test function, always fails.

    However, since you are calling CoInitialize right after that (although with an invalid pointer, you should not pass), it works when you create your thread after that.
    Hence, if you do not call test, COM is not intialized yet, so that is why creating your COM object fails in the thread.

    So you should do something like this

    CoInitialize(0); // So pass 0, instead of some pointer!

    However, since you are using COM cross thread, you could also look at CoInitializeEx and pass COINIT_MULTITHREADED as second parameter. Look this up in the MSDN documentation.

    Now you can create COM objects, using QAxObject and setControl, which should now work.
    When you are done using COM, call CoUninitialize(); to release COM stuff.

    And that should work

  12. #12
    Join Date
    Apr 2011
    Posts
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Thumbs up Re: Access a COM object from a 3rd party dll across threads

    Thanks for the tips on CoInitialize(); been chasing that problem for a week.

  13. #13
    Join Date
    Jul 2012
    Posts
    4
    Thanks
    3

    Default Re: Access a COM object from a 3rd party dll across threads

    Hi,
    I'm facing the same problem, but the above codes do not work for me... i have a compile time error "CoInitialize has not been declared" and cannot find any Qt documentation about this. Do you use MSVC compiler, and what includes do you have to access this function?
    Thanks!

  14. #14
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Access a COM object from a 3rd party dll across threads

    It's nothing to do with Qt. CoInitialize() is a deprecated Windows API call, http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx, declared in objbase.h but typically included via windows.h and ole2.h. The ActiveQt server startup code calls the equivalent function on your behalf anyway.
    "We can't solve problems by using the same kind of thinking we used when we created them." -- Einstein
    If you are posting code then please use [code] [/code] tags around it - makes addressing the problem easier.

  15. #15
    Join Date
    Jan 2013
    Posts
    6
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Access a COM object from a 3rd party dll across threads

    Quote Originally Posted by ChrisW67 View Post
    The ActiveQt server startup code calls the equivalent function on your behalf anyway.
    So what's wrong if the error remains?

    I have the following error after a second thread is started:
    Qt Code:
    1. QAxBase: Error calling IDispatch member Version: Unknown error
    To copy to clipboard, switch view to plain text mode 

  16. #16
    Join Date
    Dec 2012
    Posts
    90
    Thanks
    5
    Thanked 20 Times in 18 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Access a COM object from a 3rd party dll across threads

    You should call CoInitializeEx in every thread that uses COM. ActiveQt initializes GUI thread for you, but for every extra thread you need to call CoInitializeEx/CoUninitialize,

    Another thing, on VS I had to use ::CoInitializeEx(i.e. using global namespace modifier)

  17. The following user says thank you to lanz for this useful post:

    Maxbester (11th April 2013)

  18. #17
    Join Date
    Jan 2013
    Posts
    6
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Access a COM object from a 3rd party dll across threads

    Quote Originally Posted by lanz View Post
    You should call CoInitializeEx in every thread that uses COM. ActiveQt initializes GUI thread for you, but for every extra thread you need to call CoInitializeEx/CoUninitialize,

    Another thing, on VS I had to use ::CoInitializeEx(i.e. using global namespace modifier)
    Okay thanks.

    To be sure, when to call CoInitializeEx? I guess in the object constructor before instantiating any COM object.

  19. #18
    Join Date
    Dec 2012
    Posts
    90
    Thanks
    5
    Thanked 20 Times in 18 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Access a COM object from a 3rd party dll across threads

    No, see http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx

    CoInitializeEx should be called once per thread, say right after it started. And of course before instantiating any COM object.

Similar Threads

  1. Replies: 8
    Last Post: 23rd July 2010, 08:53
  2. How do I access data between threads
    By yodasoda in forum Qt Programming
    Replies: 3
    Last Post: 26th February 2010, 19:10
  3. How to access an object inside a privateslot
    By graciano in forum Qt Programming
    Replies: 7
    Last Post: 21st January 2009, 18:09
  4. Access an object stored in the list.
    By cbarmpar in forum General Programming
    Replies: 2
    Last Post: 21st September 2008, 20:19
  5. Access an object from another file.
    By cbarmpar in forum General Programming
    Replies: 1
    Last Post: 6th September 2008, 22:17

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.