Thread overview | |||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 14, 2014 C++ Binding Generator | ||||
---|---|---|---|---|
| ||||
I've been thinking about how to generate bindings for C++ (esp. Qt!) for a little while now. Unfortuneatly, I won't have time to implement anything until my semester is over, but with the recent talk of projects, maybe someone else will pick it up before then. Qt bindings come up every so often; they are not going to be written manually. The existing Qdd[1] was a port of Qt Jambi[2], which was the Java binding. This makes some sense, since Java is also an object-oriented language that isn't C++. Qt Jambi consists of two parts: a generator and generated code. The generator reads the Qt headers as well as XML files that describe how to map the C++ into Java. The generator creates both C++ and Java files that get compiled into a JNI library. Given that D is conceptually closer to C++ than Java, I think that binding to D should be easier than Java. Another issue here is that both Qt Jambi and QtD target Qt 4 and not version 5. Also relevant is that the libclang bindings in Deimos[3] are 2 years and several versions old (3.1 -> 3.4 is out). This is probably due to the lack of interest in libclang from D programmers (No surprise. Who wants to write code in D to parse C(++)?). It binds to libclang's C interface and may have been generated with DStep. Here's my proposed path forward: Write a binding generator in C++ that uses libclang to parse headers and auxillary XML / json / etc. files to guide the generation of D source. Clang provides data structures for traversing the C++ AST. This tool could be used to bind Qt 5 and libclang so the conversion tool can eventually be migrated to D. My hope is that using clang to avoid writing another C++ parser and D's similarity to C++ make this an easier (though still significant) undertaking than the Java bindings. I suspect that there are several patterns in C++ and D that are implemented using slightly different constructions in each of them. For instance, figuring out which C++ classes should map to D structs. Automatically identifying these or finding a description language for them would be a huge benefit to automation. On the other hand, I don't yet see a way to map generic containers (such as QList<T>) into D yet. But Qt Jambi found some way to solve this problem even when dealing with type erasure in Java. Thoughts? Thanks for reading my wall of text. Paul O'Neil [1] QtD is not actively maintained. It existed on BitBucket: https://bitbucket.org/qtd/repo before someone else forked it and moved to GitHub: https://github.com/qtd-developers/qtd [2] Homepage (appears dead): http://qt-jambi.org/ Gitorious (shows recent activity): https://qt.gitorious.org/qt-jambi [3] Github: https://github.com/D-Programming-Deimos/libclang [4] Clang: http://clang.llvm.org An example of using Clang to find CXXRecordDecl (classes, unions, structs, and the like): http://clang.llvm.org/docs/RAVFrontendAction.html |
February 15, 2014 Re: C++ Binding Generator | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul O'Neil | On Friday, 14 February 2014 at 23:52:43 UTC, Paul O'Neil wrote:
> I've been thinking about how to generate bindings for C++ (esp. Qt!) for a little while now. Unfortuneatly, I won't have time to implement anything until my semester is over, but with the recent talk of projects, maybe someone else will pick it up before then.
Why wouldn't you want to expand on DStep and add support for C++, it already uses clang?
|
February 15, 2014 Re: C++ Binding Generator | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul O'Neil | > [1] > QtD is not actively maintained. It existed on > BitBucket: https://bitbucket.org/qtd/repo > before someone else forked it and moved to > GitHub: https://github.com/qtd-developers/qtd Probably worth mentioning. There are also some recent startup efforts to generate qt bindings based on smoke qt. https://github.com/w0rp/dqt https://github.com/GlobecSys/smoke.d However, its qt4. |
February 15, 2014 Re: C++ Binding Generator | ||||
---|---|---|---|---|
| ||||
Posted in reply to michaelc37 | On Sat, 2014-02-15 at 03:36 +0000, michaelc37 wrote: > > [1] > > QtD is not actively maintained. It existed on > > BitBucket: https://bitbucket.org/qtd/repo > > before someone else forked it and moved to > > GitHub: https://github.com/qtd-developers/qtd There is https://bitbucket.org/michaelc37/qtd-experimental as well. This was a bit active for a while but has gone quiet recently. > Probably worth mentioning. > There are also some recent startup efforts to generate qt > bindings based on smoke qt. > > https://github.com/w0rp/dqt https://github.com/GlobecSys/smoke.d > > However, its qt4. If using Qt let's stick to Qt5 and not create brand new legacy APIs. In the Pythonverse, Riverbank have some mechanism for creating their Python bindings, but I bet the tool is proprietary. PySide used some binding generation tool that appears to have to be rewritten for Qt5 so they are staying with Qt4. This has stopped the PyQt → PySide rush for licencing reasons, people are just using PyQt5 and finding ways round the licencing problems. -- Russel. ============================================================================= Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder@ekiga.net 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder |
February 15, 2014 Re: C++ Binding Generator | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | On 2014-02-15 04:04, Jesse Phillips wrote: > Why wouldn't you want to expand on DStep and add support for C++, it > already uses clang? Yes, it's using libclang. -- /Jacob Carlborg |
February 15, 2014 Re: C++ Binding Generator | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul O'Neil | On 2014-02-15 00:52, Paul O'Neil wrote: > Also relevant is that the libclang bindings in Deimos[3] are 2 years and > several versions old (3.1 -> 3.4 is out). This is probably due to the > lack of interest in libclang from D programmers (No surprise. Who wants > to write code in D to parse C(++)?). I originally create those bindings to be used by DStep. But never bother updating them after that. DStep contains its own bindings. I haven't updated the bindings to anything later than 3.1 since I don't use any of these features yet. > It binds to libclang's C interface and may have been generated with DStep. Actually, I just did some simple search-and-replace on the original C header. libclang is the easiest binding I've created :) > Here's my proposed path forward: > Write a binding generator in C++ that uses libclang to parse headers and > auxillary XML / json / etc. files to guide the generation of D source. > Clang provides data structures for traversing the C++ AST. This tool > could be used to bind Qt 5 and libclang so the conversion tool can > eventually be migrated to D. My hope is that using clang to avoid > writing another C++ parser and D's similarity to C++ make this an easier > (though still significant) undertaking than the Java bindings. Why not contribute to DStep? > I suspect that there are several patterns in C++ and D that are > implemented using slightly different constructions in each of them. For > instance, figuring out which C++ classes should map to D structs. > Automatically identifying these or finding a description language for > them would be a huge benefit to automation. > > On the other hand, I don't yet see a way to map generic containers (such > as QList<T>) into D yet. But Qt Jambi found some way to solve this > problem even when dealing with type erasure in Java. You could hard code a couple of these containers. QList<T> could be converted to T[] or a linked list. I've done that with a couple of other types: like "BOOL" is translated to "bool" and "wchar_t" is translated to "wchar". -- /Jacob Carlborg |
February 15, 2014 Re: C++ Binding Generator [OT] | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Saturday, 15 February 2014 at 11:25:09 UTC, Jacob Carlborg wrote:
> and "wchar_t" is translated to "wchar".
That doesn't seem correct, it should be `wchar` on Windows only, and `dchar` on other systems, i.e. it should translate to core.stdc.stddef.wchar_t.
|
February 15, 2014 Re: C++ Binding Generator [OT] | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jakob Ovrum | On 2014-02-15 12:54, Jakob Ovrum wrote: > That doesn't seem correct, it should be `wchar` on Windows only, and > `dchar` on other systems, i.e. it should translate to > core.stdc.stddef.wchar_t. I was mistaken. Currently DStep recognizes the "wchar_t" typedef, then it checks the size of it, translating to either "wchar" or "dchar". This is correct but will not generate cross-platform bindings. core.stdc.stddef.wchar_t seems like a better choice. Thanks. -- /Jacob Carlborg |
February 15, 2014 Re: C++ Binding Generator | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul O'Neil | Can SWIG[1] be used to help here? It even supports D somehow. As I understand, Python uses SIP[2] to create Qt and other bindings. [1]http://www.swig.org/ [2]http://www.riverbankcomputing.co.uk/software/sip/intro |
February 15, 2014 Re: C++ Binding Generator | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul O'Neil | I'm working on a C++ binding generator that is coming on well, called Smidgen (first there was SWIG, then sip, now Smidgen...). I have a small demo working with both VTK and the beginnings of Qt5 GUI. I have to pick it back up (after moving house with my family) so would like help on various things such as building it on Windows (currently Linux 64bit only but it's only the build system that is Linux specific, and it's cmake so should be easy to get going on Windows). The code is tested and just-about one-click build. Currently it's in a subversion repository but I plan to move to github. I'd love someone to use Smidgen to try wrapping a small C++ library as I think it would make the job quite easy, if anyone reads this (since I have not formally announced the thing yet) then please let me know and I'll get the code out there). I have targeted the sip format binding specification (as used in sip / pyqt) so that I then get a Qt binding on the cheap (but it will therefore be GPL only). It is going well and as I said I have wrapped a small part of Qt GUI using it (and the PyQt sip files) which demonstrates working: * Using the PyQt sip files is working and I am parsing nearly all sip tags - extending to the rest of the PyQt sip files should not be _too_ arduous * Subclassing a wrapped C++ class, and overriding protected and virtual functions (e.g. paint method and mouseMoveEvent) * Nested classes (e.g. Qt::Connection) * Multiple packages / modules * Enums half-done * Sip Transfer, TransferThis and TransferBack annotations for method arguments (which govern object ownership) * Multiple C++ inheritance => multiple pointers (still needs a little bit of work but generally there) * An automated route for type conversion e.g. QString <-> D string - needs a bit more work for e.g. QList My TODO List ============ * non-primitive Typedefs * Primitive types C -> D conversion - *.conf file %CToDType long = long %CToDType unsigned char = ubyte (half done) * Sip If clauses for timelines %Timeline {Qt_5_0_0 Qt_5_0_1 Qt_5_0_2} (half done) * KeepReference for arguments + tests for Transfer etc. - Easy, in class with KeepRef e.g. View.setModel(model /KeepReference/) it has an extra attribute - void* setModel_SMIKeepRef then in setModel() { View_setModel_SMIX23(model.wrappedObject); setModel_SMIKeepRef = model; } This will make D keep a reference to the model as long as the View instance is alive. Each view will have its own reference so the total can go above 1 for a given model. * getCastPointerForInterface can be easily improved by not switching on a name but instead each class has a separate variable for each base class pointer, that is populated in the constructor - each class has one extra pointer per interface implemented - override virtual void*[] getExtraPointers() { void*[] extraPointers = super.getExtraPointers(); extraPointers ~= wrappedObject_Calculator; return extraPointers; } - in constructor this() { wrappedObject_Calculator = castRectAsCalculator(wrappedObject); } - in destructor ~this() { deregisterWrappedObject(wrappedObject); deregisterWrappedObejct(wrappedObject_Calculator); } * instance_wrapper et al., need to also register base class pointers * getWrappedObject / getClassName - how to handle this in a x-module fashion. * Add support for wrapping members * Add QTest support * int arguments that take a default enum value & enum defaults * char** -> Use this _idea_ this(string[] args) { // if (m_instance != null) // throw new RuntimeException("QCoreApplication can only be initialized once"); argc = cast(int)args.length; argv = toStringzArray(args); this(&argc, argv); // m_instance.aboutToQuit.connect(m_instance, "disposeOfMyself()"); } * Threading? - wrappedObjects[] should be shared as with CPP instance tracker. Use signal.d's WeakRef and InvisibleAddress * qRegisterMetaType?? * Add %UsesConverter to package.sip, so that the correct includes are in the package and we don't get problems trying to include e.g. widget.h in core.so * Converted types that are returned are not passed through getWrapper - might cause duplicate D objects around same C++ object e.g. QList<QWidget>? Is this a problem? * In CPP wrapper, the conversion from argument can have a memory leak (e.g. new string created and not deleted) BETTER - pass new type in as a reference if possible * Enums don't have C++ value if it was specified - need a CPP program that writes a text file e.g. Color::Red 124 Color::Green 234 and then write enum wrappers which include the values using the text lookup (at build time of wrapper NOT at runtime of final program) * Operator overloading - do nicely in D * Free function operator overloads in CPP * Handle array arguments * Multiple inheritance - if a method returns an instance of an interface and it has been created by CPP then the *Impl is returned - it is not currently typechecked. We should instead check if it's already on a registered object. * Interfaces - allow virtual calls on the interface * Lifetime management - VTK? * VTK/ Qt differences - have factory methods for Method, Klass, Package etc., and different wrapping flavours can have differing factories. Needs API stability. * Virtual functions, overloading etc. - will the right call be made if from an inherited class I make a call on an inherited D class method for a virtual method - will it call the C++ base equivalent, thereby not calling the correct virtual call on the derived class? See GOTW 5, calling virtual funcs on a base pointer will not call the derived class method. * Answer to above Q - yes, so need to implement wrappers for all inherited virtual functions even if not mentioned in SIP file * Signals and slots * Enums declared inside classes * In CPP wrapper class remove factory function/private constructor - it is not reqd. * Nested classes and multiple inheritance combination probably not working (e.g. Klass.getWrappedClassName) |
Copyright © 1999-2021 by the D Language Foundation