RE: Implicit casting issues when binding to C++

  • From: "Janis Britals" <jbritals@xxxxxxxxx>
  • To: <luajit@xxxxxxxxxxxxx>
  • Date: Mon, 9 Jul 2012 13:16:02 +0200

Michal Kottman wrote:

> However, QString has several useful methods, which were lost 
> in the conversion (you dealt only with Lua strings, which 
> were mapped to QStrings in lqt). So a decision was made to 
> map Lua string to QByteArray instead (which was really a 
> better idea, since QByteArray represents a sequence of bytes 
> of a certain length, which is exactly what Lua string is). 
> However, this decision meant that you had to type the QString 
> constructor everywhere (which as I said is a lot, when 
> implementing the GUI yourself). I used this shortcut, but it was not
> nice:
> function Q(s) return QString.fromUtf8(s) end btn = 
>"Push button label")

Actually QByteArray also has it's own semantics in Qt (e.g. it can be used
as QDataStream).

My approach was to strictly separate bindings from usage (as far as
possible), i.e. I tried to make 100% of Qt functionality available to Lua
without introducing any extra conventions. Using FFI made this task much
easier, since I could pass now any type of argument to Qt functions.
So in the case of Lua strings I treated them as FFI sees them - as "const
char *" and nothing more (well, with an implicit length in certain
contexts). So if you wanted, you could make a QByteArray of them (say
QByteArray("Text")), or QString (QString("Text")). Myself, I prefer to use
the very handy 'tr' function of Qt, so I use tr("Text") almost everywhere.
I've actually disabled the implicit QString constructors by #defining
NO_CAST_FROM_ASCII (which also automatically disables the implicit cast to
QString in Lua, so, for example, QLabel("Text") will now complain about bad
argument type so that I wouldn't forget to use 'tr'). If you wanted, you
could, of course, omit this #define, allowing you to happily write
QLabel("Text"), and implict conversions would kick in for you (thanks to
that little hack that I posted at the start of this thread).

> TL;DR implicit casting is useful, in my case when 
> constructing the GUI in Lua code and dealing with string 
> conversions. How this could be implemented with the FFI is 
> questionable (a "__construct" metamethod maybe? therefore 
> only types created using ffi.metatype would be "slowed down" 
> by the conversions...)

I agree about the usefulness of implicit casting. My implementation in FFI
was to look up the conversion function in the metatype of the argument when
the supplied type was different from what was expected and then to call it.
Usually it would be the corresponding implicit C++ constructor. Thanks to
the awsome efficiency of FFI it would take just marginally more cycles than
the same implicit conversion in C++ itself! There is no "slowdown" to speak
of. The only thing is that that needs support from FFI core, so I'm really
hoping that sometime in the near future Mike will come up with his
"lightweight generalized conversion extension" he talked about in his post.
Until then I have to rely on my little hack, which I hope to get straight
now with the help of Mike's comments.


Other related posts: