Add Objectice C Class to Qt project and call it from Qt C++ Class. How?
-
Hello all!
I am trying to implement Objective C Class into Qt Project and got failed with it. Is there any step by step guidance of this process?
The symptoms:
-- do not see #import <Foundation/Foundation.h>
-- showing the warning (see the attached images)
-- at time of compiling attempt failing with errors
-
Hi,
Can you post the content of your Objective-C code ? Not images because it makes things tedious to test.
-
@SGaist It's very simple and working perfectly in XCode project
Header file:
#import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface ocBackend : NSObject - (void) driveAuto : (NSString *) direction; - (void) openTheDoor; - (void) pushGas; - (void) carMoving; - (void) rotateSteringWheel : (NSString *) direction; @end NS_ASSUME_NONNULL_END
Class file:
#import "ocBackend.h" @implementation ocBackend - (void) driveAuto : (NSString *) direction { NSLog(@"driveAuto"); [self openTheDoor]; [self rotateSteringWheel:direction]; [self pushGas]; [self carMoving]; } - (void) openTheDoor { NSLog(@"openTheDoor"); } - (void) pushGas { NSLog(@"pushGas"); } - (void) carMoving { NSLog(@"carMoving"); } - (void) rotateSteringWheel : (NSString *) direction { if ([direction isEqualToString:@"Left"]) { NSLog(@"direction is %@",direction); } else { NSLog(@"rotateSteringWhel %@",direction); } } - (NSString *) string: (NSString *)vStringOne StringTwo: (NSString *)vStringTwo { NSString *vResult = [NSString stringWithFormat:@"String1: %@, String2: %@",vStringOne,vStringTwo]; return vResult; } @end
-
How are you using ocBackend ?
-
@SGaist There was:
-- attempt to call it from Qt/C++ class via including *.h (O-C header file) into CPP Class (look on attached image)
-- attempt to only compile without any implementing to another C Classes (previous screenshots from this attempt)It's looking like QtCreator doesn't see the MacOS libraries and don't recognise the Objective-C files.
I found this feature Objective-C++ (as I see it's looking like mix of C++ and Objective C) but it's in Apple Archive. Could it help me?
-
I haven't found why previous not working. I am publishing the project that is working perfectly. Follow published files below. It is whole project. It has been testing on iOS. All of compiler errors was relating to hidden methods from Objective-C.
Briefly solution looks like: declaring Objective-C methods like methods of C++ Class
Example published in Github repositoryAdditionally this project demonstrating writing custom QML component out on C++ that containing the Objective-C inclusions . The code line looks like Objective-C >>> C++ Custom QML Component >>> QML (QtQuick) Application
My own commentary to it - it's NOT F-WORDING trivial way!!! The devil in details ... 3 days of experiments.
QT += quick CONFIG += c++11 # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Refer to the documentation for the # deprecated API to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ main.cpp \ qmlcustomcomponent.cpp RESOURCES += qml.qrc # Additional import path used to resolve QML modules in Qt Creator's code model QML_IMPORT_PATH = # Additional import path used to resolve QML modules just for Qt Quick Designer QML_DESIGNER_IMPORT_PATH = # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target HEADERS += \ qmlcustomcomponent.h LIBS += -framework Foundation OBJECTIVE_SOURCES += MyNotification.mm OBJECTIVE_HEADERS += mynotification.h
qmlcustomcomponent.h
#ifndef QMLCUSTOMCOMPONENT_H #define QMLCUSTOMCOMPONENT_H #include <QObject> #include <QString> class QMLCustomComponent : public QObject { Q_OBJECT Q_PROPERTY(QString text READ text CONSTANT) public: explicit QMLCustomComponent(QObject *parent = nullptr); virtual ~QMLCustomComponent(); QString text(void); signals: public slots: }; #endif // QMLCUSTOMCOMPONENT_H
main.cpp
// System includes #include <QGuiApplication> #include <QQmlApplicationEngine> #include "qmlcustomcomponent.h" // Application includes // Constants const QString Main = "qrc:/main.qml"; // QtQuick Application int main(int Counter, char *Arguments[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication Application(Counter, Arguments); qmlRegisterType<QMLCustomComponent>("Custom.Component",1,0,"CustomComponent"); QQmlApplicationEngine Engine; Engine.load(QUrl(Main)); if (Engine.rootObjects().isEmpty()) return -1; return Application.exec(); }
mynotification.h
#ifndef MYNOTIFICATION_H #define MYNOTIFICATION_H #include <QString> class MyNotification { public: static void Display(const QString& title, const QString& text); static std::string Text(void); }; #endif // MYNOTIFICATION_H
#include "mynotification.h" #import <Foundation/NSString.h> void MyNotification::Display(const QString& title, const QString& text) { NSString* titleStr = [[NSString alloc] initWithUTF8String:title.toUtf8().data()]; NSString* textStr = [[NSString alloc] initWithUTF8String:text.toUtf8().data()]; NSLog(@"titleStr: %@, textStr: %@",titleStr,textStr); } std::string MyNotification::Text(void) { std::string String = "String from *.mm"; return String; }
qmlcustomcomponent.cpp
#include "qmlcustomcomponent.h" #include "mynotification.h" QMLCustomComponent::QMLCustomComponent(QObject *parent) : QObject(parent) { } QMLCustomComponent::~QMLCustomComponent(){ } QString QMLCustomComponent::text(void) { MyNotification::Display("aaa","bbbbb"); QString vString = QString::fromStdString(MyNotification::Text()); return vString; }
main.qml
// System includes import QtQuick 2.9 import QtQuick.Window 2.3 import Custom.Component 1.0 // Application includes // Application window Window { visible: true; width: 640; height: 480; title: qsTr("Hello World"); CustomComponent { id: customComponent; } Text { id: text; text: qsTr(customComponent.text); } }
qml.qrc
<RCC> <qresource prefix="/"> <file>main.qml</file> </qresource> </RCC>
-
The technique is: don't put anything Objective-C in the header you will you use in your C++ code. You can take a look at the QtMacExtras module to see the technique in action. Also the Cocoa backend in Qt's sources.