Add more helper functions to the exgractor classes.

Make it possible to distinguish between virtual and pure-virtual methods.
Switch to %AutoPyName and don't automatically use /PyName/ just to drop the leading 'wx'
Write %ModuleHeaderCode items before %Include items

git-svn-id: https://svn.wxwidgets.org/svn/wx/sandbox/trunk/Phoenix@66195 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2010-11-18 08:25:38 +00:00
parent 548d52253c
commit 5d686a914f
3 changed files with 145 additions and 21 deletions

View File

@@ -4,7 +4,7 @@
# #
# Created: 3-Nov-2010 # Created: 3-Nov-2010
# Copyright: (c) 2010 by Total Control Software # Copyright: (c) 2010 by Total Control Software
# Licence: wxWindows license # License: wxWindows License
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
""" """
@@ -107,6 +107,9 @@ class BaseDef(object):
def addItem(self, item):
self.items.append(item)
def insertItem(self, index, item): def insertItem(self, index, item):
self.items.insert(index, item) self.items.insert(index, item)
@@ -343,7 +346,8 @@ class MethodDef(FunctionDef):
def extract(self, element, className): def extract(self, element, className):
super(MethodDef, self).extract(element) super(MethodDef, self).extract(element)
self.isStatic = element.get('static') == 'yes' self.isStatic = element.get('static') == 'yes'
self.isVirtual = element.get('virt') == 'virtual' self.isVirtual = element.get('virt') in ['virtual', 'pure-virtual']
self.isPureVirtual = element.get('virt') == 'pure-virtual'
self.isCtor = self.name == className self.isCtor = self.name == className
self.isDtor = self.name == '~' + className self.isDtor = self.name == '~' + className
self.protection = element.get('prot') self.protection = element.get('prot')
@@ -515,7 +519,10 @@ class ClassDef(BaseDef):
def addCppMethod(self, type, name, argsString, body, doc=None, **kw): def addCppMethod(self, type, name, argsString, body, doc=None, **kw):
""" """
Add a new C++ method to a class. Add a new C++ method to a class. This method doesn't have to actually
exist in the real C++ class. Instead it will be grafted on by the
back-end wrapper generator such that it is visible in the class in the
target language.
""" """
md = CppMethodDef(type, name, argsString, body, doc, **kw) md = CppMethodDef(type, name, argsString, body, doc, **kw)
self.items.append(md) self.items.append(md)
@@ -549,6 +556,65 @@ class ClassDef(BaseDef):
return pc return pc
def addPublic(self, code=''):
"""
Adds a 'public:' protection keyword to the class, optionally followed
by some additional code.
"""
text = 'public:'
if code:
text = text + '\n' + code
self.addItem(WigCode(text))
def addProtected(self, code=''):
"""
Adds a 'protected:' protection keyword to the class, optionally followed
by some additional code.
"""
text = 'protected:'
if code:
text = text + '\n' + code
self.addItem(WigCode(text))
def addPrivate(self, code=''):
"""
Adds a 'private:' protection keyword to the class, optionally followed
by some additional code.
"""
text = 'private:'
if code:
text = text + '\n' + code
self.addItem(WigCode(text))
def addCopyCtor(self, prot='protected'):
# add declaration of a copy constructor to this class
wig = WigCode("""
{PROT}:
{CLASS}(const {CLASS}&);
""".format(CLASS=self.name, PROT=prot))
self.addItem(wig)
def addPrivateCopyCtor(self):
self.addCopyCtor('private')
def addPrivateAssignOp(self):
# add declaration of an assignment opperator to this class
wig = WigCode("""
private:
{CLASS}& operator=(const {CLASS}&);
""".format(CLASS=self.name))
self.addItem(wig)
def addDtor(self, prot='protected'):
# add declaration of a destructor to this class
wig = WigCode("""
{PROT}:
~{CLASS}();
""".format(CLASS=self.name, PROT=prot))
self.addItem(wig)
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
class EnumDef(BaseDef): class EnumDef(BaseDef):

View File

@@ -4,7 +4,7 @@
# #
# Created: 3-Nov-2010 # Created: 3-Nov-2010
# Copyright: (c) 2010 by Total Control Software # Copyright: (c) 2010 by Total Control Software
# Licence: wxWindows license # License: wxWindows License
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
""" """
@@ -46,15 +46,18 @@ class SipWrapperGenerator(generators.WrapperGeneratorBase):
// This file is generated by wxPython's SIP generator. Do not edit by hand. // This file is generated by wxPython's SIP generator. Do not edit by hand.
// //
// Copyright: (c) 2010 by Total Control Software // Copyright: (c) 2010 by Total Control Software
// Licence: wxWindows license // License: wxWindows License
""") """)
if module.name == module.module: if module.name == module.module:
stream.write(""" stream.write("""
%%Module(name=%s.%s, use_argument_names=True, language="C++") %%Module(name=%s.%s, use_argument_names=True, language="C++")
{
%%AutoPyName(remove_leading="wx")
}
%%Copying %%Copying
Copyright: (c) 2010 by Total Control Software Copyright: (c) 2010 by Total Control Software
Licence: wxWindows license License: wxWindows License
%%End %%End
""" % (module.package, module.name)) """ % (module.package, module.name))
@@ -68,7 +71,7 @@ class SipWrapperGenerator(generators.WrapperGeneratorBase):
# This file is generated by wxPython's SIP generator. Do not edit by hand. # This file is generated by wxPython's SIP generator. Do not edit by hand.
# #
# Copyright: (c) 2010 by Total Control Software # Copyright: (c) 2010 by Total Control Software
# Licence: wxWindows license # License: wxWindows License
%s %s
from %s import * from %s import *
@@ -80,7 +83,14 @@ from %s import *
stream.write("//\n// This file will be included by %s.sip\n//\n" % module.module) stream.write("//\n// This file will be included by %s.sip\n//\n" % module.module)
stream.write(divider) stream.write(divider)
# C++ code to be written to the module's header
if module.headerCode:
stream.write("\n%ModuleHeaderCode\n")
for c in module.headerCode:
stream.write('%s\n' % c)
stream.write("%End\n\n")
# %Imports and %Includes # %Imports and %Includes
for i in module.imports: for i in module.imports:
stream.write("%%Import %s.sip\n" % i) stream.write("%%Import %s.sip\n" % i)
@@ -89,12 +99,6 @@ from %s import *
stream.write("%%Include %s.sip\n" % i) stream.write("%%Include %s.sip\n" % i)
# C++ code to be written out to the generated module # C++ code to be written out to the generated module
if module.headerCode:
stream.write("\n%ModuleHeaderCode\n")
for c in module.headerCode:
stream.write('%s\n' % c)
stream.write("%End\n\n")
if module.cppCode: if module.cppCode:
stream.write("%ModuleCode\n") stream.write("%ModuleCode\n")
for c in module.cppCode: for c in module.cppCode:
@@ -181,14 +185,14 @@ from %s import *
name = enum.name name = enum.name
if name.startswith('@'): if name.startswith('@'):
name = '' name = ''
stream.write('%senum %s%s\n{\n' % (indent, name, self.annotate(enum))) stream.write('%senum %s%s\n%s{\n' % (indent, name, self.annotate(enum), indent))
values = [] values = []
for v in enum.items: for v in enum.items:
if v.ignored: if v.ignored:
continue continue
values.append("%s %s%s" % (indent, v.name, self.annotate(v))) values.append("%s %s%s" % (indent, v.name, self.annotate(v)))
stream.write(',\n'.join(values)) stream.write(',\n'.join(values))
stream.write('%s\n};\n\n' % (indent, )) stream.write('%s\n%s};\n\n' % (indent, indent))
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
@@ -344,7 +348,10 @@ from %s import *
stream.write('\n') stream.write('\n')
self.generateParameters(method.items, stream, indent+' '*4) self.generateParameters(method.items, stream, indent+' '*4)
stream.write(indent) stream.write(indent)
stream.write(')%s;\n\n' % self.annotate(method)) stream.write(')')
if method.isPureVirtual:
stream.write(' = 0')
stream.write('%s;\n\n' % self.annotate(method))
if method.overloads: if method.overloads:
for m in method.overloads: for m in method.overloads:
self.generateMethod(m, stream, indent) self.generateMethod(m, stream, indent)
@@ -385,7 +392,8 @@ from %s import *
def annotate(self, item): def annotate(self, item):
annotations = [] annotations = []
if item.pyName: if item.pyName:
annotations.append('PyName=%s' % item.pyName) if not getattr(item, 'wxDropped', False):
annotations.append('PyName=%s' % item.pyName)
if isinstance(item, extractors.ParamDef): if isinstance(item, extractors.ParamDef):
if item.out: if item.out:

View File

@@ -4,7 +4,7 @@
# #
# Created: 3-Nov-2010 # Created: 3-Nov-2010
# Copyright: (c) 2010 by Total Control Software # Copyright: (c) 2010 by Total Control Software
# Licence: wxWindows license # License: wxWindows License
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
""" """
@@ -18,7 +18,10 @@ import extractors
def removeWxPrefixes(node): def removeWxPrefixes(node):
""" """
Rename items with a 'wx' prefix to not have the prefix. Rename items with a 'wx' prefix to not have the prefix. If the back-end
generator supports auto-renaming then it can ignore the pyName value for
those that are changed here. We'll still change them all incase the
pyNames are needed elsewhere.
""" """
for item in node.allItems(): for item in node.allItems():
if not item.pyName \ if not item.pyName \
@@ -27,9 +30,13 @@ def removeWxPrefixes(node):
and not isinstance(item, (extractors.TypedefDef, and not isinstance(item, (extractors.TypedefDef,
extractors.MethodDef )): # TODO: Any others? extractors.MethodDef )): # TODO: Any others?
item.pyName = item.name[2:] item.pyName = item.name[2:]
item.wxDropped = True
if item.name.startswith('wxEVT_'):
# give these theire actual name so the auto-renamer won't touch them
item.pyName = item.name
def ignoreAssignmentOperators(node): def ignoreAssignmentOperators(node):
""" """
Set the ignored flag for all class methods that are assignment operators Set the ignored flag for all class methods that are assignment operators
@@ -169,3 +176,46 @@ def convertTwoDoublesTemplate(CLASS):
""".format(**locals()) """.format(**locals())
def convertFourDoublesTemplate(CLASS):
return """\
// is it just a typecheck?
if (!sipIsErr) {{
if (sipCanConvertToType(sipPy, sipType_{CLASS}, SIP_NO_CONVERTORS))
return 1;
if (PySequence_Check(sipPy) && PySequence_Size(sipPy) == 4) {{
int rval = 1;
PyObject* o1 = PySequence_ITEM(sipPy, 0);
PyObject* o2 = PySequence_ITEM(sipPy, 1);
PyObject* o3 = PySequence_ITEM(sipPy, 2);
PyObject* o4 = PySequence_ITEM(sipPy, 3);
if (!PyNumber_Check(o1) || !PyNumber_Check(o2) || !PyNumber_Check(o3) || !PyNumber_Check(o4))
rval = 0;
Py_DECREF(o1);
Py_DECREF(o2);
Py_DECREF(o3);
Py_DECREF(o4);
return rval;
}}
return 0;
}}
// otherwise do the conversion
if (PySequence_Check(sipPy)) {{
PyObject* o1 = PySequence_ITEM(sipPy, 0);
PyObject* o2 = PySequence_ITEM(sipPy, 1);
PyObject* o3 = PySequence_ITEM(sipPy, 2);
PyObject* o4 = PySequence_ITEM(sipPy, 3);
*sipCppPtr = new {CLASS}(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2),
PyFloat_AsDouble(o3), PyFloat_AsDouble(o4));
Py_DECREF(o1);
Py_DECREF(o2);
return sipGetState(sipTransferObj);
}}
*sipCppPtr = reinterpret_cast<{CLASS}*>(sipConvertToType(
sipPy, sipType_{CLASS}, sipTransferObj, SIP_NO_CONVERTORS, 0, sipIsErr));
return 0;
""".format(**locals())