QtCS2015 QtRemoteObjects

From Qt Wiki
Jump to: navigation, search

There was late-scheduled session on QtRemoteObjects at QtCS on Saturday. QtRemoteObjects is a playground module for object remoting of QObjects, and can be found at http://code.qt.io/cgit/playground/qtremoteobjects.git/ .

A brief overview of the existing features:

  • Exports QObjects remotely, creates a replicant on the client side you can interface with
  • Network nodes can serve as a registry to allow lookup by name.
  • Transport Layer Adapters
  • Bjoern is currently working on exporting of QAbstractItemModels

A brief overview of planned features:

  • Protocol Layer Adapters
  • Investigate merge with QWebChannel (sounds similar, of course no-one working on QWebChannel was present to confirm).

After it is established with those features and solid quality, it could be considered to promote it to an add-on module.

The idea with protocol adapters is that currently it only sends QDataStream output over the wire. I want to send more accessible JSON-RPC (like) data over the wire for working with node, and Attila had a demo of getting object data from Meteor (although that was custom hacked for demo purposes). Protocol adapters will allow you to serialize it in these other forms, and that is the mechanism by which we gain compatibility with other languages/frameworks without them needing explicit QRO support - We'll talk their language if there exists compatible semantics. They'll probably remain separate from the transport adapters, but we'll see how the implementation develops. I'll start looking into the implementation this month.

The question was raised "How is this not CORBA?". I'm not that familiar with CORBA (just read the wikipedia article today), but my suspicion is that we've cut out a lot of the boiler-plate by leveraging existing Qt Meta-object information. We have a base case where we aren't a generic "anything to anything" layer. We have a very specific "Qt to Qt" layer which is far easier to use, and it can be extended to be "Anything to Anything" but you'll probably end up doing as much or more work as CORBA if Qt isn't on either side (side note: I'm expecting "Qt to JS/JSON" to be another simplified case by comparison). The convenience of just being able to hook up objects remotely in QML - without having to write an extra IDL beforehand (it comes from moc data) - seems transformative. We may even be able to write a CORBA protocol adapter that would allow it to interoperate with CORBA on the other side, although it would probably be a lot of work that no-one wants and would have worse performance.

I was prototyping my own remote objects in QML until I talked to KDAB at QtCS - my implementation is nascent and will be silently discarded in favor of contributing to QtRemoteObjects. But to start the QML API draft, here's what I had in my separate implementation:

        QtObject {
            id: testCase
            property int test: 1
        RemotingServer {
            id: server
            target: testCase //This object will be remoted
            //Note that URL scheme (http here) selects transport/protocol adapter
            url: "http://localhost:3071/" //This is the location it is served at
            onRunningChanged: console.log("Server running on " + url); //running property is true iff successfully remoted
        RemotingClient {
            id: client
            url: server.url //This is the location of the remote instance
            property int test: 99 //This is a property on the remote instance we want to listen to. Until the remote connection is made, it will have a default value of 99

            //See below description
            objectName: "client"
            promotable: true
            //Note it's its own target when not promoted

The objectName and promotable properties combine to support a specific use-case I was thinking of. If you expose a QObject from C++ to QML it's usually exposed like engine.rootContext()->setContextProperty("app", appInstance). If you use remoting to serve appInstance from another node, you can export the remote object in the same place (just on the root context) and leave the UI code unchanged. All you need is a shell around it that looks like {RemotingClient{promotable:true} MyRealUI {}} when launching it on the remote host. The way I implemented it so far it actually checks that property in the root context first, so that you can have a RemotingClient{} on the local version which just does nothing and doesn't get in the way (the URL ended up being left unset in my example, so it didn't even try to start network communications).

Sharing objectName with QObject is primarily a hack for convenience, I don't like the "promotable" name so when someone thinks of a better name we can use something like <betterName>Name.