Hi

Kevin Ollivier wrote:
> Hi Eric,
> 
> On Apr 9, 2009, at 11:18 AM, Eric Kow wrote:
> 
> > On Thu, Apr 09, 2009 at 18:57:29 +0100, Eric Kow wrote:
> >> This is where Kevin Ollivier of wxWidgets pointed out something
> >> interesting: in the current wxWidgets trunk, it should be possible to
> >> automatically generate the C bindings from the Doxygen XML output.   
> >> In
> >> fact, he has already done something similar for Python, metadata to
> >> Python objects:
> >>
> >> http://trac.wxwidgets.org/browser/wxWidgets/trunk/docs/doxygen/doxymlparser.py
> >
> > Following up on this, I did
> >
> >  svn checkout http://svn.wxwidgets.org/svn/wx/wxWidgets/trunk  
> > wxWidgets
> >  cd wxWidgets/doc/doxygen
> >  ./regen.sh
> >  python doxymlparser.py --report out/xml/classwx_button.xml
> >
> > Attached is the XML file (input) and the output of this script.
> >
> > Here is a small extract of the output:
> >
> >  Class: wxButton
> >  Bases: wxControl
> >  Inlcudes: []
> >  Brief Description:
> >
> > And...
> >
> >  Method: SetLabel
> >  Return Type: void
> >  Params: [{u'type': u'const&', u'declname': u'label'}]
> >  Prototype: void wxButton::SetLabel(const wxString &label)
> >  Brief Description:
> >
> > What can we do with this?
> 
> As a start, with a few lines of Python code after the  
> doxyparser.parse(file) calls in the script, you can do something like:
> 
> # start code to autogenerate wxc.h
> wxc_header = ""
> 
> for aclass in doxyparse.classes:
>       for amethod in methods:
>               self_ref = "TSelf"
>               if amethod.name == "Create":
>                       self_ref = "TClass"
>                       wxc_header += "%s(%s) " % (self_ref, aclass.name)
>               else:
>                       wxc_header += "%s " % 
> (wxc_type_for_type(amethod.return_type)
> 
>               wxc_header += "%s_%s( %s _obj" % (aclass.name, amethod.name,  
> self_ref + (" + aclass.name + ")")
> 
>               for param in amethod.params:
>                       wxc_header += ", %s %s" % 
> (wxc_type_for_type(param["type"]), "_" +  
> param["declname"])
>                       # Note: uncomment this if you support adding default 
> values
>                       # if "defval" in param:
>                       #       wxc_header += "=" + param["defval"]
>               wxc_header += " );\n"
> 
> wxc_file = open("wxc.h", "wb")
> wxc_file.write(wxc_header)
> wxc_file.close()
> 
> # end code
> 
> This is all just pseudo-code, and methods like wxc_type_for_type would  
> need implemented, and you'd also need to probably work out some  
> special logic for constructors, a list of classes to exclude, etc. but  
> this should give you an idea of how to start things off. Ideally you'd  
> actually have your own generate_c_bindings.py file that does an  
> "import doxyparser", then runs "doxyparse.parse()" itself rather than  
> extending the doxymlparser.py script, but anyway, just some ideas.

I have made an initial attempt at a c_wrapper.py program. It is far from
finished, but like the XSLT program, I did it to see if it was feasible.
I have attached the program.

My initial imprecision is that this could work out. Python is a very
nice language, and it was a joy to make my little program. I am already
further along than with the XSLT program, and I have spend a third of
the time. And more importantly, it did not feel painful at all.

I had to change doxymlparser.py a bit though, otherwise we get
type-names like constwxString:

> svn diff:

Index: doxymlparser.py
===================================================================
--- doxymlparser.py     (revision 60099)
+++ doxymlparser.py     (working copy)
@@ -98,7 +98,11 @@
         if child.nodeType == child.ELEMENT_NODE and child.nodeName == "ref":
             text += getTextValue(child)
         if child.nodeType == child.TEXT_NODE:
-            text += child.nodeValue.strip()
+            #text += child.nodeValue.strip()
+            # We changed line above to remove qualifiers. Maybe we need 
another field on parameters?
+            for token in string.split(child.nodeValue.strip()):
+                if (token != "virtual" and token != "static" and token != 
"const"):
+                    text += token
             
     return text

Kevin, what do you think about this change?


The output looks like:

> python c_wrapper.py out/xml/classwx_button.xml | indent

/* Constructor */
       wxButton wxButton_wxButton ();
/* Constructor */
     wxButton wxButton_wxButton (wxWindow * _parent, wxWindowID _id,
                                 wxString & _label, wxPoint & _pos,
                                 wxSize & _size, long _style,
                                 wxValidator & _validator, wxString & _name);
     void wxButton_Destruct (wxButton * _obj);
     bool wxButton_Create (wxButton _obj, wxWindow * _parent, wxWindowID _id,
                           wxString & _label, wxPoint & _pos, wxSize & _size,
                           long _style, wxValidator & _validator,
                           wxString & _name);
     wxString wxButton_GetLabel (wxButton _obj);
     wxWindow *wxButton_SetDefault (wxButton _obj);
     void wxButton_SetLabel (wxButton _obj, wxString & _label);
     wxSize wxButton_GetDefaultSize (wxButton _obj);


Greetings,

Mads Lindstrøm


"""
Name: c_wrapper.py
Author: Mads Lindstroem
License: wxWidgets License
"""


#!/usr/bin/env python

import doxymlparser
import optparse
import sys


parser = optparse.OptionParser(usage="usage: %prog <doxyml files to parse>\n" , version="%prog 1.0")

options, arguments = parser.parse_args()


def wxc_type_for_type(type):
    return type


if __name__ == "__main__":
    if len(arguments) < 1:
        parser.print_usage()
        sys.exit(1)
    
    doxyparse = doxymlparser.DoxyMLParser()
    for arg in arguments:
        doxyparse.parse(arg)        

    #    for aclass in doxyparse.classes:
    #        print str(aclass)

    wxc_header = "/* \n\n Start of c-output \n\n */ \n"
    
    for aclass in doxyparse.classes:
        for amethod in aclass.methods:
            #wxc_header += str(amethod)

            this_type = wxc_type_for_type(aclass.name)
            
            print "Methodname %s Methodname" % (amethod.name)
            if amethod.name == aclass.name:
                wxc_header += "/* Constructor */\n"
                wxc_header += "%s %s_%s(" % (this_type, this_type, this_type)
                set_comma = False

            elif amethod.name == "~" + aclass.name :
                wxc_header += "void %s_Destruct(%s * _obj" % (this_type, this_type)
                set_comma = True

            else:
                wxc_header += "%s %s_%s(%s _obj" % \
                    ( wxc_type_for_type(amethod.return_type), aclass.name, amethod.name, this_type)
                set_comma = True

            for param in amethod.params:
                if set_comma:
                    wxc_header += ", "
                
                wxc_header += "%s %s" % (wxc_type_for_type(param["type"]), "_" + param["declname"])
                set_comma = True
                # Note: uncomment this if you support adding default values
                # if "defval" in param:
                #       wxc_header += "=" + param["defval"]
            
            wxc_header += " );\n"

    print wxc_header


------------------------------------------------------------------------------
This SF.net email is sponsored by:
High Quality Requirements in a Collaborative Environment.
Download a free trial of Rational Requirements Composer Now!
http://p.sf.net/sfu/www-ibm-com
_______________________________________________
wxhaskell-users mailing list
wxhaskell-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wxhaskell-users

Reply via email to