[Kde-bindings] Fwd: making smoke/korundum generate bindings for other things?

Gábor Lehel illissius at gmail.com
Wed Jul 6 12:17:37 UTC 2005


it seems I pressed reply instead of reply all, yet again. forwarding
so that other people can see it, should they want to.
(as for progress, i'm currently in the 'gathering willpower for a
second run at it' stage)
---------- Forwarded message ----------
From: Gábor Lehel <illissius at gmail.com>
Date: Jun 27, 2005 8:00 PM
Subject: Re: [Kde-bindings] making smoke/korundum generate bindings
for other things?
To: Richard Dale <Richard_Dale at tipitina.demon.co.uk>


On 6/26/05, Richard Dale <Richard_Dale at tipitina.demon.co.uk> wrote:
> On Saturday 25 June 2005 22:42, Gábor Lehel wrote:
> > Could you give a quick overview of what writing marshallers consists
> > of (eg, just a quick list, of what I have to add, and where)? I tried
> > defining a valuelist macro for KCPathDataList in kdehandlers.cpp, as
> > well as adjusting the KURL::List one to KCPathDataList after that, and
> > whilst it compiled (not sure whether the former did), it doesn't work
> > (returns a NULL pointer) -- this seems to be because smoke knows about
> > KURL, but doesn't know about KCPathData (why? are structs (as opposed
> > to classes) not processed?).
> Did you add an entry to the KDE_handlers array?
>
> TypeHandler KDE_handlers[] = {
>     ...
>     { "KCPathDataList&", marshall_KCPathDataList },
Yes, I did.


> But looking at the KCanvasPath.h header, it looks to me as though
> KCPathDataLists shouldn't be marshalled to ruby Arrays because it has methods
> like moveTo(), lineTo() and curveTo() which would be missing as an Array. So
> I think it should appear as a KDE::CPathDataList class in ruby. You may need
> to add some of the methods from QValueList so that you can insert and remove
> elements. One of the limitations of the current Smoke code generation is that
> it misses the methods from a template based superclass like
> 'QValueList<KCPathData>'.
>
> You will need to wrap the KCPathData struct seperately from Smoke as it
> doesn't have any accessor methods. See the code for wrapping the UDSAtom
> struct in Korundum.cpp - you need to add ruby accessor methods for each of
> the struct's fields.
Actually, I doubt either KCPathData or the QValueList part of
KCPathDataList need to be visible in Ruby, from what I can see they're
both intended for internal KCanvas usage only. Only moveTo, lineTo,
curveTo, and closeSubpath are necessary. I added the necessary stuff
for that to Korundum.cpp, but then it says 'Cannot handle
'KCPathDataList' as return-type of KCanvasCreator::createRectangle
'. So I tried adding a handler in kdehandlers.cpp as well; as Ruby
doesn't have to actually care about any of the internals (as opposed
to what seems like the rest of the handlers in there), I tried both
Data_Wrap_Struct and Data_Get_Structing, and set_obj_info /
value_obj_infoing the KCPathDataList; with the former it KCrashed in
iirc get_VALUEtype(); with the latter, it complained that it expected
a Class and not a nil, most likely caused by KCPathDataList not being
in Smoke's classes list (I was unable to find a way to add it). I also
tried setting kcpathdatalist_class to an rb_define_class or
rb_define_class_under instead of Qnil at the top Qt.cpp, and I can't
remember what effect that had, but either way it didn't work.
So, it's pretty obvious that I'm doing something wrong, again. The
fact that all the rest of the stuff in kdehandlers.cpp deals with
pointers and lists/arrays (where they have to be Ruby-visible) leads
me to think I'm not looking in the right place.


> > I think I also managed to figure out what generate.pl doesn't like
> > about KCanvasMatrix, KCanvasResource, and classes deriving from it:
> > functions that return a reference. How do I deal with those?
> Can you send me your current list of headers in kde_header_list, and anything
> else I need to build the same code as you have? I can fix kalyptus code
> generation problems in the svn, as it won't affect any existing code
> generation for people who don't want to use KCanvas.
Sure, here's svn diff: (with the nonworking implementation I stopped trying at):

Index: qtruby/rubylib/qtruby/Qt.cpp
===================================================================
--- qtruby/rubylib/qtruby/Qt.cpp(revision 427706)
+++ qtruby/rubylib/qtruby/Qt.cpp(working copy)
@@ -100,6 +100,7 @@
 VALUE kconfigskeleton_itemenum_class = Qnil;
 VALUE kconfigskeleton_itemenum_choice_class = Qnil;
 VALUE kio_udsatom_class = Qnil;
+VALUE kcpathdatalist_class = Qnil;
 VALUE kwin_class = Qnil;
 bool application_terminated = false;
 };
@@ -2420,6 +2421,9 @@
 } else if (packageName.startsWith("KDE::")) {
 klass = rb_define_class_under(kde_module, package+strlen("KDE::"),
qt_base_class);
 rb_define_singleton_method(klass, "new", (VALUE (*) (...)) _new_kde, -1);
+if (packageName == "KDE::CPathDataList") {
+kcpathdatalist_class = klass;
+}
 } else if (packageName.startsWith("KParts::")) {
 klass = rb_define_class_under(kparts_module,
package+strlen("KParts::"), qt_base_class);
 rb_define_singleton_method(klass, "new", (VALUE (*) (...)) _new_kde, -1);
Index: korundum/rubylib/korundum/Korundum.cpp
===================================================================
--- korundum/rubylib/korundum/Korundum.cpp(revision 427706)
+++ korundum/rubylib/korundum/Korundum.cpp(working copy)
@@ -30,6 +30,7 @@
 #include <kconfigskeleton.h>
 #endif
 #include <kio/global.h>
+#include <kcanvas/KCanvasPath.h>

 #include <ruby.h>

@@ -43,6 +44,7 @@
 extern VALUE kconfigskeleton_class;
 extern VALUE kconfigskeleton_itemenum_choice_class;
 extern VALUE kio_udsatom_class;
+extern VALUE kcpathdatalist_class;
 extern VALUE set_obj_info(const char * className, smokeruby_object * o);
 extern void set_kde_resolve_classname(const char *
(*kde_resolve_classname) (Smoke*, int, void *));
 extern const char * kde_resolve_classname(Smoke* smoke, int classId,
void * ptr);
@@ -1114,6 +1116,43 @@
 #endif

 static VALUE
+kcpathdatalist_moveto(VALUE self, VALUE x, VALUE y)
+{
+smokeruby_object *o = value_obj_info(self);
+KCPathDataList * list = (KCPathDataList *) o->ptr;
+list->moveTo(NUM2DBL(x), NUM2DBL(y));
+return self;
+}
+
+static VALUE
+kcpathdatalist_lineto(VALUE self, VALUE x, VALUE y)
+{
+smokeruby_object *o = value_obj_info(self);
+KCPathDataList * list = (KCPathDataList *) o->ptr;
+list->lineTo(NUM2DBL(x), NUM2DBL(y));
+return self;
+}
+
+static VALUE
+kcpathdatalist_curveto(VALUE self, VALUE x1, VALUE y1, VALUE x2,
VALUE y2, VALUE x3, VALUE y3)
+{
+smokeruby_object *o = value_obj_info(self);
+KCPathDataList * list = (KCPathDataList *) o->ptr;
+list->curveTo(NUM2DBL(x1), NUM2DBL(y1), NUM2DBL(x2), NUM2DBL(y2),
NUM2DBL(x3), NUM2DBL(y3));
+return self;
+}
+
+static VALUE
+kcpathdatalist_closesubpath(VALUE self)
+{
+smokeruby_object *o = value_obj_info(self);
+KCPathDataList * list = (KCPathDataList *) o->ptr;
+list->closeSubpath();
+return self;
+}
+
+
+static VALUE
 udsatom_str(VALUE self)
 {
 smokeruby_object *o = value_obj_info(self);
@@ -1215,6 +1254,11 @@
 rb_define_method(kio_udsatom_class, "m_long=", (VALUE (*) (...))
set_udsatom_long, 1);
 rb_define_method(kio_udsatom_class, "m_uds=", (VALUE (*) (...))
set_udsatom_uds, 1);

+rb_define_method(kcpathdatalist_class, "moveTo", (VALUE (*) (...))
kcpathdatalist_moveto, 2);
+rb_define_method(kcpathdatalist_class, "lineTo", (VALUE (*) (...))
kcpathdatalist_lineto, 2);
+rb_define_method(kcpathdatalist_class, "curveTo", (VALUE (*) (...))
kcpathdatalist_curveto, 6);
+rb_define_method(kcpathdatalist_class, "closeSubpath", (VALUE (*)
(...)) kcpathdatalist_closesubpath, 0);
+
 rb_require("KDE/korundum.rb");
 }

Index: korundum/rubylib/korundum/kdehandlers.cpp
===================================================================
--- korundum/rubylib/korundum/kdehandlers.cpp(revision 427706)
+++ korundum/rubylib/korundum/kdehandlers.cpp(working copy)
@@ -51,9 +51,11 @@
 #include <dom/dom_element.h>
 #include <dom/dom_string.h>
 #include <dom/html_element.h>
+#include <kcanvas/KCanvasPath.h>

 extern "C" {
 extern VALUE set_obj_info(const char * className, smokeruby_object * o);
+extern VALUE kcpathdatalist_class;
 };

 extern bool isDerivedFromByName(Smoke *smoke, const char *className,
const char *baseClassName);
@@ -317,6 +319,50 @@
 }
 }

+void marshall_KCPathDataList(Marshall *m) {
+switch(m->action()) {
+case Marshall::FromVALUE:
+{
+m->item().s_voidp = value_obj_info(*(m->var()))->ptr;
+m->next();
+kdDebug() << 1 << endl;
+if(m->cleanup()) ;
+break;
+}
+case Marshall::ToVALUE:
+{
+KCPathDataList *list = (KCPathDataList *) m->item().s_voidp;
+if (list == 0) {
+  *(m->var()) = Qnil;
+  kdDebug() << "oops!" << endl;
+  break;
+}
+
+kdDebug() << 3 << endl;
+VALUE obj = getPointerObject(list);
+if(obj == Qnil) {
+    smokeruby_object  * o = ALLOC(smokeruby_object);
+    o->smoke = m->smoke();
+    o->classId = m->smoke()->idClass("KCPathDataList");
+    o->ptr = list;
+    o->allocated = false;
+    kdDebug() << 7 << endl;
+    obj = set_obj_info("KDE::CPathDataList", o);
+}
+
+kdDebug() << 2 << endl;
+*(m->var()) = obj;
+
+if(m->cleanup())
+;
+}
+break;
+default:
+m->unsupported();
+break;
+}
+}
+
 void marshall_KServicePtr(Marshall *m) {
 switch(m->action()) {
 case Marshall::FromVALUE:
@@ -1297,6 +1343,9 @@
 { "KIO::UDSEntry&", marshall_UDSEntry },
     { "KIO::UDSEntryList&", marshall_UDSEntryList },
     { "KServiceTypeProfile::OfferList", marshall_KServiceOfferList },
+    { "KCPathDataList", marshall_KCPathDataList },
+    { "KCPathDataList&", marshall_KCPathDataList },
+    { "KCPathDataList*", marshall_KCPathDataList },
     { "KEntryMap", marshall_QMapKEntryKeyKEntry },
     { "KEntryMap&", marshall_QMapKEntryKeyKEntry },
     { "KEntryMap*", marshall_QMapKEntryKeyKEntry },
Index: kalyptus/kalyptusCxxToSmoke.pm
===================================================================
--- kalyptus/kalyptusCxxToSmoke.pm(revision 427706)
+++ kalyptus/kalyptusCxxToSmoke.pm(working copy)
@@ -170,7 +170,7 @@
    'unsigned short int' => 'ushort',
 );

-$headerSubdirectories =
"kio/|kdevelop/|kinterfacedesigner/|kontact/|kate/|kparts/|dom/|kabc/|ksettings/|kjs/|ktexteditor/|kdeprint/|kdesu/|knewstuff/"
+$headerSubdirectories =
"kcanvas/device/|kcanvas/|kio/|kdevelop/|kinterfacedesigner/|kontact/|kate/|kparts/|dom/|kabc/|ksettings/|kjs/|ktexteditor/|kdeprint/|kdesu/|knewstuff/"

 }

Index: smoke/kde/kde_header_list
===================================================================
--- smoke/kde/kde_header_list(revision 427706)
+++ smoke/kde/kde_header_list(working copy)
@@ -436,4 +436,26 @@
 knewstuff/engine.h
 knewstuff/entry.h
 knewstuff/provider.h
+kcanvas/KCanvasTypes.h
+kcanvas/KCanvasCreator.h
+kcanvas/KCanvasResourceListener.h
+kcanvas/KCanvasContainer.h
+kcanvas/KCanvas.h
+kcanvas/KCanvasImage.h
+kcanvas/KCanvasItem.h
+kcanvas/KCanvasPath.h
+kcanvas/KCanvasResources.h
+kcanvas/KCanvasMatrix.h
+kcanvas/device/KRenderingPaintServer.h
+kcanvas/device/KRenderingDeviceFactory.h
+kcanvas/device/KRenderingStrokePainter.h
+kcanvas/device/KRenderingPaintServerImage.h
+kcanvas/device/KRenderingFillPainter.h
+kcanvas/device/KRenderingDevice.h
+kcanvas/device/KRenderingPaintServerGradient.h
+kcanvas/device/KRenderingPaintServerPattern.h
+kcanvas/device/KRenderingStyle.h
+kcanvas/device/KRenderingPaintServerSolid.h
+kcanvas/KCanvasView.h
+kcanvas/KCanvasRegistry.h
+kcanvas/KCanvasFilters.h
+kcanvas/KCanvasImageBuffer.h

Index: smoke/kde/Makefile.am
===================================================================
--- smoke/kde/Makefile.am(revision 427706)
+++ smoke/kde/Makefile.am(working copy)
@@ -9,7 +9,7 @@
 libsmokekde_la_LDFLAGS = -version-info 3:2:2 -no-undefined
$(all_libraries) $(GLINC) $(KDE_RPATH)

 # the libraries to link against.
-libsmokekde_la_LIBADD   = $(LIB_KHTML) -lkjs -lfontconfig $(LIB_KMDI)
$(LIB_KNS) $(LIB_KSPELL) $(LIB_KUTILS) $(LIB_KDEPRINT) $(GLLIB)
+libsmokekde_la_LIBADD   = $(LIB_KHTML) -lkjs -lfontconfig $(LIB_KMDI)
$(LIB_KNS) $(LIB_KSPELL) $(LIB_KUTILS) $(LIB_KDEPRINT) $(GLLIB)
$(LIB_KDECORE) -lkcanvas -lkcanvasdevice

 x_sources =  x_1.cpp x_2.cpp x_3.cpp x_4.cpp x_5.cpp x_6.cpp x_7.cpp \
    x_8.cpp x_9.cpp x_10.cpp x_11.cpp x_12.cpp x_13.cpp x_14.cpp x_15.cpp \


(If you want it to actually compile, you need to remove KCanvasImage.h
and KRenderingPaintServerPattern.h, and add #include
<kcanvas/KCanvasMatrix.h> manually to the top of x_4 and x_11.cpp).

If you don't, it errors out with:
warning: KFileSharePropsPlugin inherits unknown class 'KPropsDlgPlugin'
warning: KCanvasImage inherits unknown class 'KCanvasResource'
warning: KRenderingPaintServerPattern inherits unknown class 'KCanvasResource'
Generating bindings for smoke language...
Starting writeDoc for qt...
Preparsing...
Skipping union QPDevCmdParam
Writing smokedata.cpp...
problem with KCanvasImage missing parent at kalyptusCxxToSmoke.pm line 1978.
(no errors in the 'processing so and so and so and so' part)

If you remove those two headers, it says:
Writing smokedata.cpp...
ActionType isn't a known type (type=ActionType)
DOM::DOMTimeStamp isn't a known type (type=DOM::DOMTimeStamp)
Item isn't a known type (type=Item)
KActionPtrList isn't a known type (type=KActionPtrList)
KCCapStyle isn't a known type (type=KCCapStyle)
KCColorInterpolation isn't a known type (type=KCColorInterpolation)
KCImageRendering isn't a known type (type=KCImageRendering)
KCJoinStyle isn't a known type (type=KCJoinStyle)
KCPaintServerType isn't a known type (type=KCPaintServerType)
KCPaintTargetType isn't a known type (type=KCPaintTargetType)
KCPathDataList isn't a known type (type=KCPathDataList)
KCWindRule isn't a known type (type=KCWindRule)
KCanvasMatrix isn't a known type (type=KCanvasMatrix)
KCanvasUserData isn't a known type (type=KCanvasUserData)
(...more of the same but not kcanvas...)

So, why do I think functions returning references are the problem?
$ find -type f | ruby -e '$stdin.readlines.each { |f| f.strip!;
File.readlines(f).each { |l| puts "#{f}: #{l}" if l =~ /&\w+\(/ } }'
./KCanvasResources.h:   const KCanvasItemList &clients() const;
./KCanvasMatrix.h:      KCanvasMatrix &translate(double x, double y);
./KCanvasMatrix.h:      KCanvasMatrix &multiply(const KCanvasMatrix &other);
./KCanvasMatrix.h:      KCanvasMatrix &scale(double scaleFactorX,
double scaleFactorY);
./KCanvasMatrix.h:      KCanvasMatrix &rotate(double angle);
./KCanvasMatrix.h:      KCanvasMatrix &rotateFromVector(double x, double y);
./KCanvasMatrix.h:      KCanvasMatrix &flipX();
./KCanvasMatrix.h:      KCanvasMatrix &flipY();
./KCanvasMatrix.h:      KCanvasMatrix &skewX(double angle);
./KCanvasMatrix.h:      KCanvasMatrix &skewY(double angle);
./device/KRenderingStrokePainter.h:     KCDashArray &dashArray() const;
./device/KRenderingPaintServerGradient.h:
KCSortedGradientStopList &gradientStops() const;
./KCanvasView.h:        const QColor &backgroundColor() const;
./KCanvasView.h:        const QPoint &pan() const;
./KCanvasTarget.h:      virtual const QColor &backgroundColor();
(apparently if they return a reference to a 'known type' that's okay,
which is why I tried adding them to kalyptusDataDict.pm)

and if we check what inherits from KCanvasResource:
kcanvas $ grep 'public KCanvasResource' -r *
KCanvasFilters.h:class KCanvasFilter : public KCanvasResource
KCanvasImage.h:class KCanvasImage : public KCanvasResource
KCanvasResources.h:class KCanvasClipper : public KCanvasResource
KCanvasResources.h:class KCanvasMarker : public KCanvasResource
device/KRenderingPaintServerPattern.h:
         public KCanvasResource
device/KRenderingPaintServerGradient.h:
          public KCanvasResource


and what classes in KCanvas aren't being korundumized:
kcanvas $ find -type f | xargs cat | ruby -e 'require "Korundum"; k =
KDE.constants.collect { |c| c.to_s }; puts $stdin.readlines.select {
|l| l=~ /class \w+/ }.collect { |l| l = l.split(" ")[1]; if l =~ /;$/
then l.chop! end; l[0,1] == "K" ? l[1,100] : l }.uniq.sort.collect {
|c| k.include?(c) ? nil : c }.compact'
CClipDataList
CIFilter
CPathDataList
CSortedGradientStopList
CanvasClipper
CanvasFEBlend
CanvasFEColorMatrix
CanvasFEComponentTransfer
CanvasFEComposite
CanvasFEConvolveMatrix
CanvasFEDiffuseLighting
CanvasFEDisplacementMap
CanvasFEDistantLight
CanvasFEFlood
CanvasFEGaussianBlur
CanvasFEImage
CanvasFEMerge
CanvasFEMorphology
CanvasFEOffset
CanvasFEPointLight
CanvasFESpecularLighting
CanvasFESpotLight
CanvasFETile
CanvasFETurbulence
CanvasFilter
CanvasFilterEffect
CanvasFilterQuartz
CanvasImage
CanvasMarker
CanvasMatrix
CanvasPrivateUserData
CanvasResource
CanvasTarget
CanvasTargetQt
CanvasWidget
HelperWidget
Private
QColor
QImage
QPixmap
QRect
QString
RenderingPaintServerGradient
RenderingPaintServerLinearGradient
RenderingPaintServerPattern
RenderingPaintServerRadialGradient
class (okay, so my algorithm isn't perfect)

then clearly, a pattern starts to become visible.



> It would be harder to do
> a version of Korundum.cpp and kdehandlers.cpp that could be built
> conditionally for KCanvas though. You would need some sort of
> '--enable-kcanvas=yes' configure flag, with suitable #ifdefs in the C++ code,
> and only link against libkdecore and libkcanvas if that was true.
Well, I'm perfectly fine to have it just in my local copy for now
(until my app gets to the point where I want to distribute it to end
users, which won't be for quite a while), but if other people also
want to work with KCanvas from Ruby then I'm fine with including it as
well...

>
> > I tried
> > adding entries for the returned types to kalyptusDataDict.pm (as I
> > remembered seeing 'type&' stuff in there), but it didn't make a
> > difference (by the way, what purpose does it serve, as I remember you
> > saying it's not necessary to add stuff to it?).
> It's obsolete and should really be removed, I'm afraid the kalyptus code has
> got a bit old and crufty in parts and needs tidying up a bit.
>
> -- Richard
>


--
Work is punishment for failing to procrastinate effectively.


-- 
Work is punishment for failing to procrastinate effectively.



More information about the Kde-bindings mailing list