mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-05 11:30:06 +01:00
Generate CppMethods as a separate function that is called from the wrapper, instead of embedding it in the wrapper itself. This helps us be less SIP-specific and also be able to do things like 'return' the value and use 'self->' instead of having to use variable names that make less sense.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@66348 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -62,7 +62,6 @@ def run():
|
||||
# platforms, and other goodies, then change the c.name so SIP will
|
||||
# generate code wrapping this class as if it was the wxApp class seen in
|
||||
# the DoxyXML.
|
||||
##c.addCppCode(wxPyApp)
|
||||
c.insertCppCode('src/app_ex.cpp')
|
||||
|
||||
for item in c.allItems(): # change the class name, ctors and dtor names
|
||||
@@ -84,7 +83,7 @@ def run():
|
||||
doc="Hide all application windows just as the user can do with the\nsystem Hide command. Mac only.",
|
||||
body="""\
|
||||
#ifdef __WXMAC__
|
||||
sipCpp->MacHideApp();
|
||||
self->MacHideApp();
|
||||
#endif
|
||||
""")
|
||||
|
||||
|
||||
@@ -36,18 +36,18 @@ def run():
|
||||
#ifdef __WXMAC__
|
||||
#include <wx/osx/private.h>
|
||||
#endif
|
||||
""")
|
||||
|
||||
module.addCppFunction('wxColour', 'MacThemeColour', '(int themeBrushID)', """\
|
||||
""")
|
||||
module.addCppFunction('wxColour*', 'MacThemeColour', '(int themeBrushID)', """\
|
||||
#ifdef __WXMAC__
|
||||
sipRes = new wxColour(wxMacCreateCGColorFromHITheme(themeBrushID));
|
||||
return new wxColour(wxMacCreateCGColorFromHITheme(themeBrushID));
|
||||
#else
|
||||
wxPyRaiseNotImplemented();
|
||||
sipIsErr = 1;
|
||||
sipRes = NULL;
|
||||
return NULL;
|
||||
#endif
|
||||
""", factory=True)
|
||||
|
||||
|
||||
# Change this macro into a value so we wont have problems when SIP takes its
|
||||
# address
|
||||
module.addCppCode("""\
|
||||
@@ -93,7 +93,7 @@ def run():
|
||||
|
||||
c.find('GetPixel').ignore() # We need to add a typcast
|
||||
c.addCppMethod('wxIntPtr', 'GetPixel', '()', """\
|
||||
sipRes = (wxIntPtr)sipCpp->GetPixel();
|
||||
return (wxIntPtr)self->GetPixel();
|
||||
""")
|
||||
|
||||
# Set a flag on the return value and parameter types that are 'unsigned char'
|
||||
@@ -123,23 +123,23 @@ def run():
|
||||
c.find('MakeMono.b').out = True
|
||||
|
||||
|
||||
c.addCppMethod('SIP_PYOBJECT', 'Get', '(bool includeAlpha=true)', """\
|
||||
c.addCppMethod('PyObject*', 'Get', '(bool includeAlpha=true)', """\
|
||||
int red = -1;
|
||||
int green = -1;
|
||||
int blue = -1;
|
||||
int alpha = wxALPHA_OPAQUE;
|
||||
if (sipCpp->IsOk()) {
|
||||
red = sipCpp->Red();
|
||||
green = sipCpp->Green();
|
||||
blue = sipCpp->Blue();
|
||||
alpha = sipCpp->Alpha();
|
||||
if (self->IsOk()) {
|
||||
red = self->Red();
|
||||
green = self->Green();
|
||||
blue = self->Blue();
|
||||
alpha = self->Alpha();
|
||||
}
|
||||
if (includeAlpha)
|
||||
sipRes = sipBuildResult(&sipIsErr, "(iiii)", red, green, blue, alpha);
|
||||
return sipBuildResult(&_isErr, "(iiii)", red, green, blue, alpha);
|
||||
else
|
||||
sipRes = sipBuildResult(&sipIsErr, "(iii)", red, green, blue);
|
||||
return sipBuildResult(&_isErr, "(iii)", red, green, blue);
|
||||
""", briefDoc="""\
|
||||
Get(includeAlpha=Valse) -> (r,g,b) or (r,g,b,a)\n
|
||||
Get(includeAlpha=False) -> (r,g,b) or (r,g,b,a)\n
|
||||
Returns the RGB intensity values as a tuple, optionally the alpha value as well.""")
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ def run():
|
||||
c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]')
|
||||
c.addPyMethod('__setitem__', '(self, idx, val)',
|
||||
"""\
|
||||
if idx == 0: self.red = val
|
||||
if idx == 0: self.red = val
|
||||
elif idx == 1: self.green = val
|
||||
elif idx == 2: self.blue = val
|
||||
elif idx == 3: self.alpha = val
|
||||
|
||||
12
etg/event.py
12
etg/event.py
@@ -133,20 +133,20 @@ def run():
|
||||
c.find('GetClientData').ignore()
|
||||
c.find('SetClientData').ignore()
|
||||
|
||||
c.addCppMethod('SIP_PYOBJECT', 'GetClientData', '()', """\
|
||||
wxPyClientData* data = (wxPyClientData*)sipCpp->GetClientObject();
|
||||
c.addCppMethod('PyObject*', 'GetClientData', '()', """\
|
||||
wxPyClientData* data = (wxPyClientData*)self->GetClientObject();
|
||||
if (data) {
|
||||
Py_INCREF(data->m_obj);
|
||||
sipRes = data->m_obj;
|
||||
return data->m_obj;
|
||||
} else {
|
||||
Py_INCREF(Py_None);
|
||||
sipRes = Py_None;
|
||||
return Py_None;
|
||||
}
|
||||
""")
|
||||
|
||||
c.addCppMethod('void', 'SetClientData', '(SIP_PYOBJECT clientData)', """\
|
||||
c.addCppMethod('void', 'SetClientData', '(PyObject* clientData)', """\
|
||||
wxPyClientData* data = new wxPyClientData(clientData);
|
||||
sipCpp->SetClientObject(data);
|
||||
self->SetClientObject(data);
|
||||
""")
|
||||
|
||||
|
||||
|
||||
25
etg/font.py
25
etg/font.py
@@ -48,19 +48,33 @@ def run():
|
||||
assert isinstance(c, etgtools.ClassDef)
|
||||
tools.removeVirtuals(c)
|
||||
|
||||
c.addCppCtor("""(
|
||||
# TODO: Since the TypeCode is inserted before the derived class
|
||||
# (sipwxFont) is defined, we can't use the new version of addCppCtor. Can
|
||||
# this be fixed?
|
||||
c.addCppCtor_sip("""(
|
||||
int pointSize,
|
||||
wxFontFamily family,
|
||||
int flags = wxFONTFLAG_DEFAULT,
|
||||
const wxString & faceName = wxEmptyString,
|
||||
wxFontEncoding encoding = wxFONTENCODING_DEFAULT
|
||||
)""",
|
||||
const wxString& faceName = wxEmptyString,
|
||||
wxFontEncoding encoding = wxFONTENCODING_DEFAULT )""",
|
||||
body="""\
|
||||
// YUCK!
|
||||
wxFont* font = wxFont::New(pointSize, family, flags, *faceName, encoding);
|
||||
sipCpp = new sipwxFont(*font);
|
||||
delete font;
|
||||
""")
|
||||
|
||||
# Same as the above, but as a factory function
|
||||
module.addCppFunction('wxFont*', 'FFont', """(
|
||||
int pointSize,
|
||||
wxFontFamily family,
|
||||
int flags = wxFONTFLAG_DEFAULT,
|
||||
const wxString& faceName = wxEmptyString,
|
||||
wxFontEncoding encoding = wxFONTENCODING_DEFAULT )""",
|
||||
body="""\
|
||||
wxFont* font = wxFont::New(pointSize, family, flags, *faceName, encoding);
|
||||
return font;
|
||||
""", factory=True)
|
||||
|
||||
|
||||
for item in c.findAll('New'):
|
||||
item.factory = True
|
||||
@@ -76,6 +90,7 @@ def run():
|
||||
c.addProperty('Underlined GetUnderlined SetUnderlined')
|
||||
c.addProperty('Weight GetWeight SetWeight')
|
||||
|
||||
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
|
||||
@@ -104,8 +104,8 @@ def run():
|
||||
# wxPoint typemap
|
||||
c.convertFromPyObject = tools.convertTwoIntegersTemplate('wxPoint')
|
||||
|
||||
c.addCppMethod('SIP_PYOBJECT', 'Get', '()', """\
|
||||
sipRes = sipBuildResult(&sipIsErr, "(ii)", sipCpp->x, sipCpp->y);
|
||||
c.addCppMethod('PyObject*', 'Get', '()', """\
|
||||
return sipBuildResult(&_isErr, "(ii)", self->x, self->y);
|
||||
""", briefDoc="""\
|
||||
Get() -> (x,y)\n
|
||||
Return the x and y properties as a tuple.""")
|
||||
@@ -157,8 +157,8 @@ def run():
|
||||
# wxSize typemap
|
||||
c.convertFromPyObject = tools.convertTwoIntegersTemplate('wxSize')
|
||||
|
||||
c.addCppMethod('SIP_PYOBJECT', 'Get', '()', """\
|
||||
sipRes = sipBuildResult(&sipIsErr, "(ii)", sipCpp->GetWidth(), sipCpp->GetHeight());
|
||||
c.addCppMethod('PyObject*', 'Get', '()', """\
|
||||
return sipBuildResult(&_isErr, "(ii)", self->GetWidth(), self->GetHeight());
|
||||
""", briefDoc="""\
|
||||
Get() -> (width, height)\n
|
||||
Return the width and height properties as a tuple.""")
|
||||
@@ -183,7 +183,8 @@ def run():
|
||||
#---------------------------------------
|
||||
# wxRect tweaks
|
||||
c = module.find('wxRect')
|
||||
|
||||
assert isinstance(c, etgtools.ClassDef)
|
||||
|
||||
c.addProperty("left GetLeft")
|
||||
c.addProperty("top GetTop")
|
||||
c.addProperty("right GetRight")
|
||||
@@ -228,9 +229,9 @@ def run():
|
||||
# wxRect typemap
|
||||
c.convertFromPyObject = tools.convertFourIntegersTemplate('wxRect')
|
||||
|
||||
c.addCppMethod('SIP_PYOBJECT', 'Get', '()', """\
|
||||
sipRes = sipBuildResult(&sipIsErr, "(iiii)",
|
||||
sipCpp->x, sipCpp->y, sipCpp->width, sipCpp->height);
|
||||
c.addCppMethod('PyObject*', 'Get', '()', """\
|
||||
return sipBuildResult(&_isErr, "(iiii)",
|
||||
self->x, self->y, self->width, self->height);
|
||||
""", briefDoc="""\
|
||||
Get() -> (x, y, width, height)\n
|
||||
Return the rectangle's properties as a tuple.""")
|
||||
@@ -277,10 +278,9 @@ def run():
|
||||
|
||||
# wxRealPoint typemap
|
||||
c.convertFromPyObject = tools.convertTwoDoublesTemplate('wxRealPoint')
|
||||
|
||||
c.addCppMethod('SIP_PYOBJECT', 'Get', '()', """\
|
||||
sipRes = sipBuildResult(&sipIsErr, "(dd)",
|
||||
sipCpp->x, sipCpp->y);
|
||||
|
||||
c.addCppMethod('PyObject*', 'Get', '()', """\
|
||||
return sipBuildResult(&_isErr, "(dd)", self->x, self->y);
|
||||
""", briefDoc="""\
|
||||
Get() -> (x, y, width, height)\n
|
||||
Return the rectangle's properties as a tuple.""")
|
||||
|
||||
@@ -59,8 +59,8 @@ def run():
|
||||
|
||||
c.convertFromPyObject = tools.convertTwoDoublesTemplate('wxPoint2DDouble')
|
||||
|
||||
c.addCppMethod('SIP_PYOBJECT', 'Get', '()', """\
|
||||
sipRes = sipBuildResult(&sipIsErr, "(dd)", sipCpp->m_x, sipCpp->m_y);
|
||||
c.addCppMethod('PyObject*', 'Get', '()', """\
|
||||
return sipBuildResult(&_isErr, "(dd)", self->m_x, self->m_y);
|
||||
""", briefDoc="""\
|
||||
Get() -> (x,y)\n
|
||||
Return the x and y properties as a tuple.""")
|
||||
@@ -93,7 +93,6 @@ def run():
|
||||
item.ignore()
|
||||
|
||||
|
||||
|
||||
c = module.find('wxRect2DDouble')
|
||||
c.pyName = 'Rect2D'
|
||||
c.find('m_x').pyName = 'x'
|
||||
@@ -103,9 +102,9 @@ def run():
|
||||
|
||||
c.convertFromPyObject = tools.convertFourDoublesTemplate('wxRect2DDouble')
|
||||
|
||||
c.addCppMethod('SIP_PYOBJECT', 'Get', '()', """\
|
||||
sipRes = sipBuildResult(&sipIsErr, "(dddd)",
|
||||
sipCpp->m_x, sipCpp->m_y, sipCpp->m_width, sipCpp->m_height);
|
||||
c.addCppMethod('PyObject*', 'Get', '()', """\
|
||||
return sipBuildResult(&_isErr, "(dddd)",
|
||||
self->m_x, self->m_y, self->m_width, self->m_height);
|
||||
""", briefDoc="""\
|
||||
Get() -> (x, y, width, height)\n
|
||||
Return the rectangle's properties as a tuple.""")
|
||||
|
||||
@@ -52,11 +52,11 @@ def run():
|
||||
assert isinstance(c, etgtools.ClassDef)
|
||||
|
||||
c.addCppMethod('const wxChar*', 'GetClassName', '()',
|
||||
body='sipRes = sipCpp->GetClassInfo()->GetClassName();',
|
||||
body='return self->GetClassInfo()->GetClassName();',
|
||||
doc='Returns the class name of the C++ class using wxRTTI.')
|
||||
|
||||
c.addCppMethod('void', 'Destroy', '()',
|
||||
body='delete sipCpp;',
|
||||
body='delete self;',
|
||||
doc='Deletes the C++ object this Python object is a proxy for.',
|
||||
transferThis=True) # TODO: Check this
|
||||
|
||||
|
||||
@@ -42,8 +42,8 @@ def run():
|
||||
c = module.find('wxRegionIterator')
|
||||
c.find('operator++').ignore()
|
||||
|
||||
c.addCppMethod('void', 'Next', '()', 'sipCpp->operator++();')
|
||||
c.addCppMethod('int', '__nonzero__', '()', 'sipRes = (int)sipCpp->operator bool();')
|
||||
c.addCppMethod('void', 'Next', '()', 'self->operator++();')
|
||||
c.addCppMethod('int', '__nonzero__', '()', 'return (int)self->operator bool();')
|
||||
|
||||
c.addProperty('H GetH')
|
||||
c.addProperty('Height GetHeight')
|
||||
|
||||
@@ -20,6 +20,9 @@ DOCSTRING = ""
|
||||
ITEMS = [ 'wxVisualAttributes',
|
||||
'wxWindow' ]
|
||||
|
||||
OTHERDEPS = [ 'src/window_ex.cpp', # some helper C++ code
|
||||
]
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
def run():
|
||||
@@ -30,10 +33,12 @@ def run():
|
||||
#-----------------------------------------------------------------
|
||||
# Tweak the parsed meta objects in the module object as needed for
|
||||
# customizing the generated code and docstrings.
|
||||
|
||||
|
||||
c = module.find('wxWindow')
|
||||
assert isinstance(c, etgtools.ClassDef)
|
||||
|
||||
c.insertCppCode('src/window_ex.cpp')
|
||||
|
||||
# ignore some overloads that will be ambiguous afer wrapping
|
||||
c.find('GetChildren').overloads = []
|
||||
c.find('GetClientSize').findOverload('int *').ignore()
|
||||
@@ -44,6 +49,10 @@ def run():
|
||||
c.find('ClientToScreen').findOverload('int *').ignore()
|
||||
c.find('ScreenToClient').findOverload('int *').ignore()
|
||||
|
||||
# Rename these overloads for symmetry with the getters of the same name
|
||||
c.find('SetSize').findOverload('wxRect').pyName = 'SetRect'
|
||||
c.find('SetClientSize').findOverload('wxRect').pyName = 'SetClientRect'
|
||||
|
||||
m = c.find('GetTextExtent').findOverload('int *')
|
||||
m.pyName = 'GetFullTextExtent'
|
||||
m.find('w').out = True
|
||||
@@ -52,32 +61,82 @@ def run():
|
||||
m.find('externalLeading').out = True
|
||||
|
||||
c.find('GetHandle').type = 'void*'
|
||||
c.find('GetHandle').setCppCode("sipRes = wxPyGetWinHandle(sipCpp);")
|
||||
|
||||
# Rename these overloads for symmetry with the getters of the same name
|
||||
c.find('SetSize').findOverload('wxRect').pyName = 'SetRect'
|
||||
c.find('SetClientSize').findOverload('wxRect').pyName = 'SetClientRect'
|
||||
c.addCppMethod('void*', 'GetGtkWidget', '()', """\
|
||||
#ifdef __WXGTK__
|
||||
return (void*)self->GetHandle();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
""")
|
||||
|
||||
# Add this method
|
||||
# Add some new methods
|
||||
c.addCppMethod('wxWindow*', 'GetTopLevelParent', '()',
|
||||
'sipRes = wxGetTopLevelParent(sipCpp);')
|
||||
'return wxGetTopLevelParent(self);')
|
||||
#c.addCppMethod('wxWindow*', 'FindWindowByLabel', '(const wxString& label)',
|
||||
# 'return wxWindow::FindWindowByLabel(label, self);')
|
||||
|
||||
# TODO: make these be available on Windows, and empty stubs otherwise
|
||||
c.find('RegisterHotKey').ignore()
|
||||
c.find('UnregisterHotKey').ignore()
|
||||
c.addCppMethod('bool', 'MacIsWindowScrollbar', '(const wxWindow* sb)', """\
|
||||
#ifdef __WXMAC__
|
||||
return self->MacIsWindowScrollbar(sb);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
""")
|
||||
|
||||
# Make these be available on Windows, and empty stubs otherwise
|
||||
c.find('RegisterHotKey').setCppCode("""\
|
||||
#ifdef __WXMSW__
|
||||
sipRes = sipCpp->RegisterHotKey(hotkeyId, modifiers, virtualKeyCode);
|
||||
#else
|
||||
sipRes = false;
|
||||
#endif
|
||||
""")
|
||||
c.find('UnregisterHotKey').setCppCode("""\
|
||||
#ifdef __WXMSW__
|
||||
sipRes = sipCpp->UnregisterHotKey(hotkeyId);
|
||||
#else
|
||||
sipRes = false;
|
||||
#endif
|
||||
""")
|
||||
c.find('RegisterHotKey').isVirtual = False
|
||||
c.find('UnregisterHotKey').isVirtual = False
|
||||
|
||||
# maybe these too
|
||||
c.find('SetDoubleBuffered').setCppCode("""\
|
||||
#if defined(__WXGTK20__) || defined(__WXMSW__)
|
||||
sipCpp->SetDoubleBuffered(on);
|
||||
#endif
|
||||
""")
|
||||
|
||||
#%Rename(ConvertDialogPointToPixels, wxPoint, ConvertDialogToPixels(const wxPoint& pt));
|
||||
#%Rename(ConvertDialogSizeToPixels, wxSize, ConvertDialogToPixels(const wxSize& sz));
|
||||
#%Rename(ConvertPixelPointToDialog, wxPoint, ConvertPixelsToDialog(const wxPoint& pt));
|
||||
#%Rename(ConvertPixelSizeToDialog, wxSize, ConvertPixelsToDialog(const wxSize& sz));
|
||||
|
||||
# MSW only. Do we want them wrapped?
|
||||
c.find('GetAccessible').ignore()
|
||||
c.find('SetAccessible').ignore()
|
||||
|
||||
# Make some of the protected methods overridable from Python
|
||||
|
||||
# Make some of the protected methods visible and overridable from Python
|
||||
c.find('DoCentre').ignore(False)
|
||||
c.find('DoGetBestSize').ignore(False)
|
||||
c.find('SetInitialBestSize').ignore(False)
|
||||
c.find('SendDestroyEvent').ignore(False)
|
||||
c.find('ProcessEvent').ignore(False)
|
||||
|
||||
c.addPyMethod('PostCreate', '()', 'pass')
|
||||
|
||||
# Define some properties using the getters and setters
|
||||
# transfer ownership of these parameters to the C++ object
|
||||
c.find('SetCaret.caret').transfer = True
|
||||
c.find('SetToolTip.tip').transfer = True
|
||||
c.find('SetDropTarget.target').transfer = True
|
||||
c.find('SetConstraints.constraints').transfer = True
|
||||
c.find('SetSizer.sizer').transfer = True
|
||||
c.find('SetSizerAndFit.sizer').transfer = True
|
||||
|
||||
# Define some properties using the getter and setter methods
|
||||
c.addProperty('AcceleratorTable GetAcceleratorTable SetAcceleratorTable')
|
||||
c.addProperty('AutoLayout GetAutoLayout SetAutoLayout')
|
||||
c.addProperty('BackgroundColour GetBackgroundColour SetBackgroundColour')
|
||||
@@ -143,9 +202,9 @@ def run():
|
||||
c.addProperty('MaxClientSize GetMaxClientSize SetMaxClientSize')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
tools.fixWindowClass(c)
|
||||
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
tools.runGenerators(module)
|
||||
|
||||
@@ -87,8 +87,6 @@ class BaseDef(object):
|
||||
raise ExtractorError("Unable to find item named '%s' within %s named '%s'" %
|
||||
(head, self.__class__.__name__, self.name))
|
||||
|
||||
|
||||
|
||||
def addItem(self, item):
|
||||
self.items.append(item)
|
||||
|
||||
@@ -155,6 +153,7 @@ class VariableDef(BaseDef):
|
||||
self.type = None
|
||||
self.definition = ''
|
||||
self.argsString = ''
|
||||
self.pyInt = False
|
||||
self.__dict__.update(**kw)
|
||||
if element is not None:
|
||||
self.extract(element)
|
||||
@@ -230,7 +229,7 @@ class FunctionDef(BaseDef):
|
||||
self.extract(element)
|
||||
|
||||
def releaseGIL(self, release=True):
|
||||
self.pyReleaseGIL = hold
|
||||
self.pyReleaseGIL = release
|
||||
|
||||
def extract(self, element):
|
||||
super(FunctionDef, self).extract(element)
|
||||
@@ -450,6 +449,9 @@ class ClassDef(BaseDef):
|
||||
return p
|
||||
|
||||
|
||||
|
||||
#------------------------------------------------------------------
|
||||
|
||||
def addCppMethod(self, type, name, argsString, body, doc=None, **kw):
|
||||
"""
|
||||
Add a new C++ method to a class. This method doesn't have to actually
|
||||
@@ -457,20 +459,42 @@ class ClassDef(BaseDef):
|
||||
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, klass=self, **kw)
|
||||
self.items.append(md)
|
||||
return md
|
||||
|
||||
|
||||
def addCppCtor(self, argsString, body, doc=None, noDerivedCtor=True, **kw):
|
||||
def addCppCtor(self, argsString, body, doc=None, noDerivedCtor=True, useDerivedName=False, **kw):
|
||||
"""
|
||||
Add a C++ method that is a constructor.
|
||||
"""
|
||||
md = CppMethodDef('', self.name, argsString, body, doc=doc,
|
||||
isCtor=True, noDerivedCtor=noDerivedCtor, **kw)
|
||||
isCtor=True, klass=self, noDerivedCtor=noDerivedCtor,
|
||||
useDerivedName=useDerivedName, **kw)
|
||||
self.items.append(md)
|
||||
return md
|
||||
|
||||
|
||||
|
||||
def addCppMethod_sip(self, type, name, argsString, body, doc=None, **kw):
|
||||
"""
|
||||
Just like the above but can do more things that are SIP specific in
|
||||
the code body, instead of using the general purpose implementation.
|
||||
"""
|
||||
md = CppMethodDef_sip(type, name, argsString, body, doc, klass=self, **kw)
|
||||
self.items.append(md)
|
||||
return md
|
||||
|
||||
def addCppCtor_sip(self, argsString, body, doc=None, noDerivedCtor=True, **kw):
|
||||
"""
|
||||
Add a C++ method that is a constructor.
|
||||
"""
|
||||
md = CppMethodDef_sip('', self.name, argsString, body, doc=doc,
|
||||
isCtor=True, klass=self, noDerivedCtor=noDerivedCtor, **kw)
|
||||
self.items.append(md)
|
||||
return md
|
||||
|
||||
#------------------------------------------------------------------
|
||||
|
||||
|
||||
def addPyMethod(self, name, argsString, body, doc=None, **kw):
|
||||
"""
|
||||
@@ -627,9 +651,20 @@ class CppMethodDef(MethodDef):
|
||||
self.body = body
|
||||
self.briefDoc = doc
|
||||
self.protection = 'public'
|
||||
self.klass = None
|
||||
self.noDerivedCtor = False
|
||||
self.__dict__.update(kw)
|
||||
|
||||
|
||||
class CppMethodDef_sip(CppMethodDef):
|
||||
"""
|
||||
Just like the above, but instead of generating a new function from the
|
||||
privided code, the code is used inline inside SIP's %MethodCode directive.
|
||||
This makes it possible to use additional SIP magic for things that are
|
||||
beyond the general scope of the other C++ Method implementation.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
@@ -784,7 +819,6 @@ class ModuleDef(BaseDef):
|
||||
return item
|
||||
|
||||
|
||||
|
||||
|
||||
def addCppFunction(self, type, name, argsString, body, doc=None, **kw):
|
||||
"""
|
||||
@@ -795,6 +829,16 @@ class ModuleDef(BaseDef):
|
||||
self.items.append(md)
|
||||
return md
|
||||
|
||||
|
||||
def addCppFunction_sip(self, type, name, argsString, body, doc=None, **kw):
|
||||
"""
|
||||
Add a new C++ function into the module that is written by hand, not
|
||||
wrapped.
|
||||
"""
|
||||
md = CppMethodDef_sip(type, name, argsString, body, doc, **kw)
|
||||
self.items.append(md)
|
||||
return md
|
||||
|
||||
|
||||
def addPyCode(self, code, order=None):
|
||||
"""
|
||||
|
||||
@@ -12,7 +12,7 @@ The generator class for creating SIP definition files from the data
|
||||
objects produced by the ETG scripts.
|
||||
"""
|
||||
|
||||
import sys, os
|
||||
import sys, os, re
|
||||
import extractors
|
||||
import generators
|
||||
from cStringIO import StringIO
|
||||
@@ -53,7 +53,7 @@ class SipWrapperGenerator(generators.WrapperGeneratorBase):
|
||||
%%Module(name=%s.%s, use_argument_names=True, language="C++")
|
||||
{
|
||||
%%AutoPyName(remove_leading="wx")
|
||||
}
|
||||
};
|
||||
|
||||
%%Copying
|
||||
Copyright: (c) 2010 by Total Control Software
|
||||
@@ -92,12 +92,15 @@ from %s import *
|
||||
stream.write("%End\n\n")
|
||||
|
||||
# %Imports and %Includes
|
||||
for i in module.imports:
|
||||
stream.write("%%Import %s.sip\n" % i)
|
||||
stream.write("\n")
|
||||
for i in module.includes:
|
||||
stream.write("%%Include %s.sip\n" % i)
|
||||
|
||||
if module.imports:
|
||||
for i in module.imports:
|
||||
stream.write("%%Import %s.sip\n" % i)
|
||||
stream.write("\n")
|
||||
if module.includes:
|
||||
for i in module.includes:
|
||||
stream.write("%%Include %s.sip\n" % i)
|
||||
stream.write("\n")
|
||||
|
||||
# C++ code to be written out to the generated module
|
||||
if module.cppCode:
|
||||
stream.write("%ModuleCode\n")
|
||||
@@ -133,14 +136,15 @@ from %s import *
|
||||
|
||||
def generateModuleItems(self, module, stream):
|
||||
methodMap = {
|
||||
extractors.ClassDef : self.generateClass,
|
||||
extractors.FunctionDef : self.generateFunction,
|
||||
extractors.EnumDef : self.generateEnum,
|
||||
extractors.GlobalVarDef : self.generateGlobalVar,
|
||||
extractors.TypedefDef : self.generateTypedef,
|
||||
extractors.WigCode : self.generateWigCode,
|
||||
extractors.PyCodeDef : self.generatePyCode,
|
||||
extractors.CppMethodDef : self.generateCppMethod,
|
||||
extractors.ClassDef : self.generateClass,
|
||||
extractors.FunctionDef : self.generateFunction,
|
||||
extractors.EnumDef : self.generateEnum,
|
||||
extractors.GlobalVarDef : self.generateGlobalVar,
|
||||
extractors.TypedefDef : self.generateTypedef,
|
||||
extractors.WigCode : self.generateWigCode,
|
||||
extractors.PyCodeDef : self.generatePyCode,
|
||||
extractors.CppMethodDef : self.generateCppMethod,
|
||||
extractors.CppMethodDef_sip : self.generateCppMethod_sip,
|
||||
}
|
||||
|
||||
for item in module:
|
||||
@@ -287,14 +291,15 @@ from %s import *
|
||||
protected = [i for i in klass if i.protection == 'protected']
|
||||
|
||||
dispatch = {
|
||||
extractors.MemberVarDef : self.generateMemberVar,
|
||||
extractors.PropertyDef : self.generateProperty,
|
||||
extractors.MethodDef : self.generateMethod,
|
||||
extractors.EnumDef : self.generateEnum,
|
||||
extractors.CppMethodDef : self.generateCppMethod,
|
||||
extractors.PyMethodDef : self.generatePyMethod,
|
||||
extractors.PyCodeDef : self.generatePyCode,
|
||||
extractors.WigCode : self.generateWigCode,
|
||||
extractors.MemberVarDef : self.generateMemberVar,
|
||||
extractors.PropertyDef : self.generateProperty,
|
||||
extractors.MethodDef : self.generateMethod,
|
||||
extractors.EnumDef : self.generateEnum,
|
||||
extractors.CppMethodDef : self.generateCppMethod,
|
||||
extractors.CppMethodDef_sip : self.generateCppMethod_sip,
|
||||
extractors.PyMethodDef : self.generatePyMethod,
|
||||
extractors.PyCodeDef : self.generatePyCode,
|
||||
extractors.WigCode : self.generateWigCode,
|
||||
# TODO: nested classes too?
|
||||
}
|
||||
for item in ctors:
|
||||
@@ -388,7 +393,94 @@ from %s import *
|
||||
|
||||
|
||||
def generateCppMethod(self, method, stream, indent=''):
|
||||
# Add a new C++ method to a class. This one adds the code as a
|
||||
# separate function and then adds a call to that function in the
|
||||
# MethodCode directive.
|
||||
assert isinstance(method, extractors.CppMethodDef)
|
||||
if method.ignored:
|
||||
return
|
||||
klass = method.klass
|
||||
if klass:
|
||||
assert isinstance(klass, extractors.ClassDef)
|
||||
|
||||
# create the new function
|
||||
fargs = method.argsString.strip('()').split(',')
|
||||
for idx, arg in enumerate(fargs):
|
||||
# take only the part before the =, if there is one
|
||||
arg = arg.split('=')[0].strip()
|
||||
arg = arg.replace('&', '*') # SIP will always want to use pointers for parameters
|
||||
fargs[idx] = arg
|
||||
fargs = ', '.join(fargs)
|
||||
if fargs:
|
||||
fargs = ', ' + fargs
|
||||
if method.isCtor:
|
||||
fname = '_%s_newCtor' % klass.name
|
||||
fargs = '(int& _isErr%s)' % fargs
|
||||
stream.write('%s%%TypeCode\n' % indent)
|
||||
typ = klass.name
|
||||
if method.useDerivedName:
|
||||
typ = 'sip'+klass.name
|
||||
stream.write('%sclass %s;\n' % (indent, typ)) # forward decalre the derived class
|
||||
stream.write('%s%s* %s%s\n%s{\n' % (indent, typ, fname, fargs, indent))
|
||||
stream.write(nci(method.body, len(indent)+4))
|
||||
stream.write('%s}\n' % indent)
|
||||
stream.write('%s%%End\n' % indent)
|
||||
|
||||
else:
|
||||
if klass:
|
||||
fname = '_%s_%s' % (klass.name, method.name)
|
||||
fargs = '(%s* self, int& _isErr%s)' % (klass.name, fargs)
|
||||
stream.write('%s%%TypeCode\n' % indent)
|
||||
else:
|
||||
fname = '_%s_function' % method.name
|
||||
fargs = '(int& _isErr%s)' % fargs
|
||||
stream.write('%s%%ModuleCode\n' % indent)
|
||||
stream.write('%s%s %s%s\n%s{\n' % (indent, method.type, fname, fargs, indent))
|
||||
stream.write(nci(method.body, len(indent)+4))
|
||||
stream.write('%s}\n' % indent)
|
||||
stream.write('%s%%End\n' % indent)
|
||||
|
||||
# now insert the method declaration and the code to call the new function
|
||||
# find the parameter names
|
||||
pnames = method.argsString.strip('()').split(',')
|
||||
for idx, pn in enumerate(pnames):
|
||||
# take only the part before the =, if there is one
|
||||
name = pn.split('=')[0].strip()
|
||||
# now get just the part after and space, * or &, which should be
|
||||
# the parameter name
|
||||
name = re.split(r'[ \*\&]+', name)[-1]
|
||||
pnames[idx] = name
|
||||
pnames = ', '.join(pnames)
|
||||
if pnames:
|
||||
pnames = ', ' + pnames
|
||||
# convert PyObject* to SIP_PYOBJECT in the return type and param types
|
||||
typ = method.type.replace('PyObject*', 'SIP_PYOBJECT')
|
||||
argsString = method.argsString.replace('PyObject*', 'SIP_PYOBJECT')
|
||||
# spit it all out
|
||||
if method.isCtor:
|
||||
stream.write('%s%s%s%s;\n' %
|
||||
(indent, method.name, argsString, self.annotate(method)))
|
||||
else:
|
||||
stream.write('%s%s %s%s%s;\n' %
|
||||
(indent, typ, method.name, argsString, self.annotate(method)))
|
||||
stream.write('%s%%MethodCode\n' % indent)
|
||||
stream.write(indent+' '*4)
|
||||
if method.isCtor:
|
||||
stream.write('sipCpp = %s(sipIsErr%s);\n' % (fname, pnames))
|
||||
else:
|
||||
if method.type != 'void':
|
||||
stream.write('sipRes = ')
|
||||
if klass:
|
||||
stream.write('%s(sipCpp, sipIsErr%s);\n' % (fname, pnames))
|
||||
else:
|
||||
stream.write('%s(sipIsErr%s);\n' % (fname, pnames))
|
||||
stream.write('%s%%End\n\n' % indent)
|
||||
|
||||
|
||||
def generateCppMethod_sip(self, method, stream, indent=''):
|
||||
# Add a new C++ method to a class without the extra generated
|
||||
# function, so SIP specific stuff can be done in the function body.
|
||||
assert isinstance(method, extractors.CppMethodDef_sip)
|
||||
if method.ignored:
|
||||
return
|
||||
if method.isCtor:
|
||||
@@ -401,7 +493,8 @@ from %s import *
|
||||
stream.write('%s%%MethodCode\n' % indent)
|
||||
stream.write(nci(method.body, len(indent)+4))
|
||||
stream.write('%s%%End\n\n' % indent)
|
||||
|
||||
|
||||
|
||||
|
||||
def generatePyMethod(self, pm, stream, indent):
|
||||
assert isinstance(pm, extractors.PyMethodDef)
|
||||
@@ -409,7 +502,7 @@ from %s import *
|
||||
pm.klass.generateAfterClass.append(pm)
|
||||
else:
|
||||
klassName = pm.klass.pyName or pm.klass.name
|
||||
stream.write("%Extract pycode\n")
|
||||
stream.write("%Extract(id=pycode)\n")
|
||||
stream.write("def _%s_%s%s:\n" % (klassName, pm.name, pm.argsString))
|
||||
if pm.briefDoc:
|
||||
stream.write(nci('"""\n%s\n"""\n' % pm.briefDoc, 4))
|
||||
@@ -445,6 +538,10 @@ from %s import *
|
||||
annotations.append('TranserThis')
|
||||
if item.pyInt:
|
||||
annotations.append('PyInt')
|
||||
|
||||
if isinstance(item, extractors.VariableDef):
|
||||
if item.pyInt:
|
||||
annotations.append('PyInt')
|
||||
|
||||
if isinstance(item, extractors.FunctionDef):
|
||||
if item.deprecated:
|
||||
@@ -524,4 +621,8 @@ def nci(text, numSpaces=0, stripLeading=True):
|
||||
return newText
|
||||
|
||||
|
||||
class SipGeneratorError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
@@ -81,7 +81,22 @@ def fixEventClass(klass):
|
||||
klass.addPrivateAssignOp()
|
||||
|
||||
|
||||
|
||||
def fixWindowClass(klass):
|
||||
"""
|
||||
Do common tweaks for a window class.
|
||||
"""
|
||||
# The ctor and Create method transfer ownership of the this pointer
|
||||
klass.find('%s.parent' % klass.name).transferThis = True
|
||||
klass.find('Create.parent').transferThis = True
|
||||
# give the id param a default value
|
||||
klass.find('%s.id' % klass.name).default = 'wxID_ANY'
|
||||
klass.find('Create.id').default = 'wxID_ANY'
|
||||
# look for wxByte parameters
|
||||
#for item in klass.allItems():
|
||||
# if hasattr(item, 'type') and item.type == 'wxByte':
|
||||
# item.pyInt = True
|
||||
|
||||
|
||||
def removeVirtuals(klass):
|
||||
"""
|
||||
Sometimes methods are marked as virtual but probably don't ever need to be
|
||||
|
||||
Reference in New Issue
Block a user