How To Call Qt/C++ OSX Dylib from Objective C



  • From Objective C, how do I load a dynamic link library (OSX calls these dylib files) class method?

    Also, will it let me do something like show the Finder Choose File window under this unusual context from the Qt dylib?

    The reason I ask is that I like the ease of coding of Qt/C++ far more than Objective C. I built a minimalist Cocoa app in Objective C only so that I could utilize the native webkit of OSX, and then learned the technique to insert Javascript into it, and then have that call a class method in Objective C. The end goal would be that I click a button like "Choose File" in the webkit, it then calls the Javascript handler for that, which then calls my "cpp" object in Javascript, which calls the Objective C class method, which then calls the Qt/C++ class method, which then calls the API fo show the Finder's Choose File window, and then returns a result back. I've managed to get the Javascript working to call an Objective C class method just fine -- but then don't know the technique to call the Qt/C++ dylib's class method from there.


  • Lifetime Qt Champion

    Hi,

    You can use Objective-C++. Then you can go on and use the usual stuff in C++ and link the libraries to your application.



  • @SGaist It didn't seem to work. Here's what I did:

    1. Created a shared dynamic link Dylib in Qt/C++ named libtestlib.1.0.0. The class name is Testlib. It had a test() class method inside that received string input and tacked on '-response', and returned that result back. I compiled it okay.

    2. Created an Objective C Cocoa-based application using the defaults.

    3. Added my testlib.h file to my ObjC project.

    4. Added my binary dylib file to my ObjC project.

    5. In my main.m file, did:

    #import "testlib.h";

    1. In my main.m file's main() function, I tried to do:
    Testlib *o = new Testlib();
    NSLog(@"Result=%@",o->test('request'));
    

    However, ObjC complains about the first line in step #6 and says:

    Use of undeclared identifier: o
    Unknown type name: Testlib
    

    Someone in a forum suggested I rename the .m to a .mm file, but that didn't work. Someone else suggested renaming the .h to an.hppfile, but that didn't work either.


  • Lifetime Qt Champion

    Do you have that sample project available somewhere ?



  • @SGaist http://volosites.com/downloads/sample.zip

    Inside are 2 zips:

    Testlib - the Qt/C++ Dylib for OSX
    Sample - the Objective C app for OSX that tries to load Testlib

    The ObjC project won't compile. In main.m, you can see where I'm trying to load the testlib.h and then call TestLib's test class method.

    I'm quite surprised that no one has posted on the web how to make this bridge possible between ObjC to Qt/C++.



  • @SGaist This seems pretty daunting -- trying to get much of the Qt framework to load for a dylib inside Objective C. Perhaps a better approach would be to just create a .mm file in my project, create an ordinary C++ class there, and use these classes to make my life a bit easier:

    #include <string>
    #include <stdio.h>
    #include <sqlite3.h>
    #include <Foundation/Foundation.h>
    

    And then instead of using Qt, do it all using C++ with string, stdio (noting this), the sqlite3 library for C++ which comes with Macs when you install XCode, and the Apple Foundation classes.

    Also, so that one doesn't have to pass std::string and convert it, here's the funky way to pass NSString between Objective C++ (loaded in XCode) and Objective C in a .mm file which lets you combine both C++ and Objective C:

    class Testlib {
    public:
      NS_RETURNS_RETAINED NSString *test(NSString *sIn) {
        // note the [[super funky Objective C syntax]]
        NSString *sOut = [[NSString alloc] init];
        sOut = [NSString stringWithFormat:@"%@-response", sIn];
        return sOut;
      }
    }
    

  • Lifetime Qt Champion

    Depending on what you would like that library to do, then indeed it might be overkill to pull Qt in.

    What should that library do (I take it the sample is not implementing the final stuff) ?



  • @SGaist Some things I needed on this project:

    • Didn't like the limitations of QML and Qt Widgets. QML was hard to use compared with just HTML and Javascript. I kept wondering why bother with QML when I could just use WebKit. Qt Widgets really required subclassing and paint intercepts to take it where I needed to take it. For instance -- imagine a table widget and you want a select all checkbox in column 1 -- not so easy. So, I used the embedded WebKit that comes with Qt 5.5. However, by doing so, I added 30MB more to the project. I got a powerful GUI just the way I wanted it, but at the expense of 30MB more in download size. Thus, I had to make a custom setup for it so that I could make a small installer download and say "Installing..." and other messages and progress bar updates while it downloaded the larger framework and installed it. But that was kind of a kludge when I could have used native webkit.

    • Qt 5.5 has a tech preview of the native webkit. However, that is just that -- a tech preview. It had lots of problems, such as not able to show a SELECT popdown listbox that works, and many other issues.

    • I prefer Qt's coding environment a whole lot more than Objective C. So, I thought I'd draw only the GUI in Objective C because then I could use a native webkit. I was going to make it simple -- just a window, menu, and the rest is all in the webkit widget. I found that there's a bridge in Objective C as well to make it such that Javascript can call an Objective C class method. However, trying to build most of the business logic of my application in Qt/C++ was going to be hard to include as a dylib inside Objective C because, well, it's super hard to set all the right settings in Objective C to make it load the right libraries and compiler tricks, as well as have the issue of string transfer from one framework to another. Plus, even if I managed to get it all working -- it would increase project size by around 10MB. It would be bundling two frameworks (Objective C and Qt) instead of one.

    • These are the things my business logic needs to do:

      • connect over HTTP to a server with a REST-like request
      • parse strings
      • file I/O
      • SQLite database interaction
      • settings save/load
      • launch a particular browser (telling ObjC to do it) for in-app upgrade purchase
      • get the user's language (telling ObjC to do it)
      • get default paths and username for the given user (telling ObjcC to do it)

    So, I then realized that I can get all that with C++ inside Objective C and XCode as long as I include some extra libraries and rename my .m file to .mm so that I can bridge ObjC to C++ and back.

    All this -- simply because Qt 5.5 doesn't have a fully working native webkit yet, and because 5.6 looks like they don't want to do that either -- they're talking about using Blink. The makers of Qt don't realize that they're increasing the application size dramatically on OSX with this strategy.


  • Lifetime Qt Champion

    What about QMacCocoaViewContainer ?



  • @SGaist said:

    QMacCocoaViewContainer

    Hmmmm! Interesting!

    I'll have to give this some thought.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.