[Interest] QCanBusDevice inheritance

Benjamin TERRIER b.terrier at gmail.com
Wed Sep 9 16:41:10 CEST 2015

2015-09-09 15:18 GMT+02:00 Blasche Alexander
<alexander.blasche at theqtcompany.com>:
> Hi,
>>Thanks for your response but I still don't get why QIODevice has been
>>discarded for CAN while it is used for QUdpSocket.
>>First, frames can always be divided into bytes, there length is an
>>integer multiple of byte. If you are talking about the fact that
>>fields within a frame are not 8 bits longs (identifier can be 11),
>>this should be handled by the underlying CAN library.
> The QIODevice architecture was not a good fit for CAN bus. The API must
> enable the user to interpret the various frames received on the bus. In
> addition to the payload, each frame may come from different sources, has
> different types and other attributes. This means that the API requires at
> least an abstraction on frame level. For each new frame that you send you
> may adjust the frame attributes as well.

Yes, CAN requires an abstraction on frame level.

> This is considerably different from a QIODevice based architecture where you
> generally open a connection to a remote entity and once the connection is
> established you merely keep exchanging payload. After all you don't set a
> new IP for each UDP datagram. There is no requirement to dissect the
> incoming data stream on the backend either. We generally copy the raw data
> to a socket.

  qint64 QUdpSocket::writeDatagram(const QByteArray & datagram, const
QHostAddress & host, quint16 port)

You do set a new IP for each UDP datagram.
And as for QUdpSocket you could have enabled a virtual connection
behavior (see last line of QUdpSocket detailed description in Qt

> Another inefficiency of the QIODevice approach would be that each frame
> would have to be serialized to a QByteArray on the user API side just to be
> unserialized on the backend side again. I have yet to see a backend API that
> doesn't deal with a frame based API. There is simply nothing gained.

I don't get why each frame would have to be serialized if
QCanBusDevice inherits QIODevice. The implementation of
QCanBusDevice::writeFrame() would not change. It would, on the other
hand, require to implement QIODevice::writeData() which would either
call QCanBusDevice::writeFrame() or directly the backend API
effectively doing some "unserialization".

> Another argument, the frame based API serves as an input gate. We can make
> assumptions about data format to be send by the API user as the user has to
> fit it into a QCanBusFrame. How should a backend react to an arbitrary data
> stream coming from the user? We have to find all the frame details in it
> before we send it further on. Hence a QIODevice API invites "frame input
> errors" which is not very user friendly.
> I hope this helps to understand the reasons for the change.
> --
> Alex
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/interest

I do agree that the QIODevice API is not a perfect fit for a CAN API
and that it is not user friendly. However, I do think it would have
been better to keep the inheritance using a frame level API as the
main entry point for QCanBusDevice, and the QIODevice API as a
fallback which would rely on the frame level API.
I think it would have been more coherent with the rest of the Qt
framework, particularly when looking at QUdpSocket.



More information about the Interest mailing list