[Kde-bindings] What should I be doing?

Ashley Winters jahqueel at yahoo.com
Sat Aug 9 23:24:26 UTC 2003


No, I'm not looking for suggestions. It's a rhetorical question. :)

In my ongoing effort to develop something which will allow
PerlQt/KDE/et al. to continue on after I become homeless and/or
convicted of theft/fraud/embezzlement, I've been working on a way to
reorganize Smoke to be a universal binding interface. So far, it seems
to be working out alright. The Ruby/Qt bindings look very functional,
and Richard's idea for integrating Java/Qt with Smoke looks entirely
feasable to me.

So, what should the future hold for Smoke? Well, KDE for one thing. The
Smoke library was designed to be extensible with a separate KDE library
interface in the same program as Qt, but the code parsers were not. In
order to do that, it's probably best to use the gcc parser to output
XML into a machine-readable format so as to extract the interface from
the compiler itself.

However, each Smoke library attempts to be a self-contained unit
containing its own "meaning" of every class. The smokekdecore library
would have its own dataset entries for QObject and friends, even though
it wouldn't provide an interface for them. This imprecise duplication
of information leads to a coordination nightmare and a Tower of Babel
type situation when attempting to communicate a simple thing like
"QWidget pointer" between kdecore and kdeui and qt.

So, we need a unified naming system to identify every
class/method/constant in a library. Amazingly enough, people have
invented a thing called URIs for just that sort of purpose. Each method
is a "resource" which is identified by a "URI" and accessed through a
"mirror" library using a "smoke" scheme/protocol/whatever.

What does it mean? It means everything gets a unique URL, and that URI
can be used to call functions. Like so:

smoke://qt@libqt-mt.so.3.1.2/QWidget/mapTo;QWidget%2a,const+QPoint%26

Lets break that down RFC2396 style.

    smoke://

Our resource is not accessible through http or any other existing
internet protocol. The Smoke library provides a distinct protocol of
marshalling arguments and passing them to functions, as well as a few
other perks. That is why we have our own URL "scheme".

    <library>@<filename>

The @<filename> is only used when trying to access the library.
Internally, each library is just referenced as smoke://qt/ or
smoke://kdecore/ and the filename is "known" through some
as-yet-unspecified mechanism. On Windows, it would be
smoke://qt@qt.dll/ of course.

    /<path>/<identifier>;<arguments>

The <path> is the URI-translated absolute name of the class/namespace
being referenced. All instances of :: in the fully-qualified name are
replaced with / along the path. ::std::strlen(const char*) would become
/std/strlen;const+char%2a.

The <arguments> is the encoded argument list of the method. The
characters ',' and '+' are reserved for use as argument separator and
space character, respectively. The rest of the argument literal should
be URL-encoded. For complex template types in argument lists, do this: 

   func(const foo<bar::baz<int,const char*> >&, int)
   func;const+foo%3cbar%3a%3a%3cint%2cconst+char%2a%3e+%3e%26,int

Note that ',' is only to be used to separate actual function arguments,
and must be escaped within template parameters!

In order to call a function, you need one hell of a URL. Try this:

    smoke://qt@libqt-mt.so.3.1.2/QWidget/
    mapTo;QWidget%2a,const+QPoint%26?return=QPoint

Everything before the ? specifies the specific resource (method) to
call, and everything after the ? specifies the various parameters as to
how to go about doing it. If you want to override a virtual method,
perhaps you use ?virtual=override. If you want the size of a QWidget,
perhaps you use smoke://qt/QWidget?info=sizeof or something. I dunno.
It's yet to be specified.

About now the question of ``Why?'' may be on your minds. In particular,
why add all that horrifying complexity and string manipulation to the
small and lean Smoke? Well, first thing is that the URI scheme is just
a representation of the Smoke interface, and I don't expect it to be
used at runtime (although the facilities to do so will be available).
The reason it's important is to allow each method to be described as a
resource through RDF. Simply having URIs for everything doesn't
describe the relationships between them. QWidget has to know it's
derived from QObject and QPaintDevice.

That's where RDF comes in. It will be the way in which the various
relationships are specified. Sadly, RDF is highly verbose and n3 is
somewhat cryptic, but here's a psuedo-example of the information which
would be available through RDF. Only a tip of the iceberg.

QWidget inherits (QObject, QPaintDevice)

QWidget/topLevelWidget returns (pointer to QWidget)
QWidget/topLevelWidget thisPointer (pointer to (constant QWidget))
QWidget/topLevelWidget documentation "Returns the top-level widget for
this widget, i.e. the next ancestor widget that has (or could have) a
window-system frame."

QWidget/QWidget constructs QWidget
QWidget/QWidget returns (pointer to QWidget)
QWidget/QWidget parameters ((pointer to QWidget, default of 0),
(pointer to C-type-char, default of 0), (C-type-unsigned-int, default
of 0))

Of course, all this information would be automatically pulled from
gcc's parser, but having a universal identifier for "QWidget"
(specifically, smoke://qt/QWidget) across every library makes things
flow together much more smoothly.

As for implementation, there would no longer be separate
smokeqt/smokekde libraries. There would be a single libsmoke through
which any library would be accessed. It could be implemented in several
ways:

1. create the mangled C++ symbol names from the URLs and call through
that way
2. replicate the current Smoke method of switch()-based method
resolution
3. wrap every method in a C function through a
libmirrorqt/kdecore/kdeui/etc library
4. steal some JIT code and generate wrapper functions on the fly using
method #1

How libsmoke is implemented in the future is not my concern; however, I
personally plan to implement #3.

Method #3 requires the creation of a set of mirror libraries, one for
each library interfaced. This mirror library would wrap every function
in the library and make it available by its URI (I plan to md5sum the
URI and use that as the symbol name).

This mirror library would be generated using the RDF description of the
resources available in the target library. Ideally, there will be a
central repository of Qt/KDE library RDF models which will know how
various #define flags affect the interface (like QT_NO_TRANSLATION) and
would change the mirror library appropriately.

I'm not sure how the actual code generation will work. I don't
particularly want to make gccxml.org's program a requirement to compile
PerlQt (only a requirement to develop) since it's out-of-date,
hard-to-fix, slow-to-progress, and it doesn't run cleanly on my system.
Instead, I'm considering just creating my own RDF specification of Qt
and KDE in the kde.org CVS using gccxml and shipping that, while
requiring people to install Redland RDF if they want to expand it.
*shrug*

Implementation is a whole other issue which I'll tackle while I'm doing
it. Comments? Suggestions? Offers to do all this for me? Job? Money?

Until the next time James Michael DuPont provides me the imspiration to
embrace-and-corrupt one of his ideas, farewell. :)

Ashley (Got Smoke?) Winters

__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com


More information about the Kde-bindings mailing list