I hope you're all sitting comfortably? Good, then we'll begin...
In today's lesson, we are going to learn why writing language bindings can, on occasion, make you wish you had a normal leisure-time activity - like hunting wabbits.
If you are using a framework/toolkit in everyday C++ you aren't (usually) going to come across an issue which has caught me on several occasions, which all to do with how a pointer is perceived when you pass it down from your higher-level language. For most of the time, everything "just works", but there are times when you are passing in, say a QPaintDevice*, and things start to get just a little weird (insofar as strange error messages that you aren't expecting).
When I say "just works", I mean that you'll declare your function parameter as said pointer type, and the call down to the framework will do its thing, no questions asked.
However, you pass it into a different function, and suddenly it is reporting errors that don't quite make sense. Many hours later and you can't see anything wrong with the code.
This is where you need to take a very large step back and ponder the problem at hand.
You should ask yourself. Is the pointer I'm passing into the function *really* a QPaintDevice, or is it actually a subclass, like say, a QWidget, in which case you may actually want to be defining the parameter as a QWidget* instead.
Why does it matter sometimes and not others?
I believe it's something to do with internal offsets inside instance of the QWidget, which although is also a QPaintDevice, is really a QWidget at heart.
Normally this is not a problem, because C++ *knows* what you are passing around. So when you say, "take this pointer as a QPaintDevice", it knows that yes it can, because it sees that it is a QWidget also.
But, when your pointer is appearing suddenly into the glure code from the higher-level language, C++ can't determine what the object really is. You tell it "this is a QPaintDevice", and it makes a whole raft of assumptions.
As you may imagine, I've been here, and solved an issue I've been having.
QPainter() takes a QPaintDevice* as a parameter. This might be a QWidget, or even a QImage (which isn't a widget), or other QPaintDevice subclasses.
When I was passing in a widget of some kind, up would pop a strange error :
- QPainter::begin: A paint device can only be painted by one painter at a time.
Which would have been fine if I'd already assigned the widget to a QPainter...
Many hours later, and some last-resort Googling, it dawns on me that I perhaps, for widgets, instead of this :
- QPainter * bmx_qt_qpainter_create(QPaintDevice * device)
I rather have this :
- QPainter * bmx_qt_qpainter_createwithwidget(QWidget * widget);
And you know what... the error went away...
... even though a QWidget is a subclass of QPaintDevice.
Well, I've rambled on for too long again... back to work!