15

I have a Qt project that can load any HTML page into a web view. I have the following code in main.cpp file:

#include "mainwindow.h"
#include <QApplication>
#include <QWebView>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWebView *view = new QWebView();

    view->resize(400, 500);
    view->load(QUrl("file:///absolute/path/to/my/html/file.html"));
    view->show();

    return app.exec();
}

This works fine, but I want to call a function from C++ side via Javascript loaded in file.html (loaded in QWebView).

So, having the following C++ function:

void sumOfNumbers (a, b)
{
   qDebug() << a + b;
}

I want to call it from Javascript side:

someMethod("sumOfNumber", 12, 23);

that will print in the console 35 (12 + 23).

How can I do this?

Ionică Bizău
  • 109,027
  • 88
  • 289
  • 474
  • possible duplicate of [Is it possible to call a C++ function from JavaScript in a QWebView?](http://stackoverflow.com/questions/9615194/is-it-possible-to-call-a-c-function-from-javascript-in-a-qwebview) – BartoszKP Oct 19 '13 at 18:19
  • Yeah, it seems to be a dup. – László Papp Oct 20 '13 at 06:46

2 Answers2

16

You need to define the methods you want to call in a class that inherits from QObject.

From a QWebView, you can call page() to retrieve its QWebPage. With a QWebPage, you can call mainFrame() to retrieve its QWebFrame. QWebFrame has a addToJavaScriptWindowObject() method which lets you bind QObject's into the web context:

class MyObject {
public slots:
    void doSomething();
};

MyObject *foo = new MyObject;
myWebView->page()->mainFrame()->addJavaScriptToWindowObject("somefoo", foo);

Then from the javascript side I can call any slot or Q_INVOKABLE method on my QObject simply by referencing it by the name provided above ("somefoo" in this case):

somefoo.doSomething();

More info here: http://qt-project.org/doc/qt-5.1/qtwebkit/qwebframe.html#addToJavaScriptWindowObject

Update - adding the original example.

main.cpp:

#include <QApplication>
#include <QDebug>
#include <QWebFrame>
#include <QWebPage>
#include <QWebView>

class MyJavaScriptOperations : public QObject {
    Q_OBJECT
public:
    Q_INVOKABLE void sumOfNumbers(int a, int b) {
        qDebug() << a + b;
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QWebView *view = new QWebView();
    view->resize(400, 500);
    view->page()->mainFrame()->addToJavaScriptWindowObject("myoperations", new MyJavaScriptOperations);
    view->load(QUrl("file:///path/to/my/index.html"));
    view->show();

    return a.exec();
}

#include "main.moc"

index.html:

<html>
    <body>
        <script type="text/javascript">
            myoperations.sumOfNumbers(12, 23);
        </script>
    </body>
</html>
ksimons
  • 3,797
  • 17
  • 17
  • can anyone tell what is main.moc ? Why is it included and what are the contents of "main.moc" – Parth Doshi Jan 28 '14 at 14:59
  • @ParthDoshi moc is the meta object compiler system that Qt uses to convert Qt-specific code in C++ (non-standard c++ code that Qt needs) into regular c++ code that the regular c++ compiler can understand. you don't normally need to interact or look at moc files – johnbakers Feb 28 '14 at 03:39
  • 1
    @ksimons I get `:-1: error: symbol(s) not found for architecture x86_64` `:-1: error: linker command failed with exit code 1 (use -v to see invocation)` with your code. Any solutions? – Niklas Apr 02 '14 at 11:28
  • @Niklas Have you rerun qmake? Maybe post your project file? – ksimons Apr 02 '14 at 12:39
5

Current accepted answer is outdated because Qt moved to WebEngine.

For WebEngineView the solution for calling Qt from JS is using Qt WebChannel API

sgt pepper
  • 504
  • 7
  • 15