aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2011-04-06 18:58:18 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-08 16:15:20 -0300
commitf107f41c2b99517133ac4d2d624e8ee61cac2bb2 (patch)
tree5a5f4961c1189468c488c81e542b923937bd9316
parent8c506130849194b0f7838a7920b5f7cc94bfe619 (diff)
Fixed the argument conversion of modified virtual methods.
Wrong conversion code was being outputted to virtual method wrapper code when all arguments were removed. Unit tests were added as well.
-rw-r--r--generator/cppgenerator.cpp15
-rw-r--r--tests/libsample/virtualmethods.cpp9
-rw-r--r--tests/libsample/virtualmethods.h21
-rw-r--r--tests/samplebinding/modifiedvirtualmethods_test.py69
-rw-r--r--tests/samplebinding/typesystem_sample.xml68
5 files changed, 161 insertions, 21 deletions
diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp
index 72ca183b6..f208241b8 100644
--- a/generator/cppgenerator.cpp
+++ b/generator/cppgenerator.cpp
@@ -549,6 +549,17 @@ void CppGenerator::writeDestructorNative(QTextStream &s, const AbstractMetaClass
s << '}' << endl;
}
+static bool allArgumentsRemoved(const AbstractMetaFunction* func)
+{
+ if (func->arguments().isEmpty())
+ return false;
+ foreach (const AbstractMetaArgument* arg, func->arguments()) {
+ if (!func->argumentRemoved(arg->argumentIndex() + 1))
+ return false;
+ }
+ return true;
+}
+
void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFunction* func)
{
//skip metaObject function, this will be written manually ahead
@@ -654,7 +665,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu
s << INDENT << "Shiboken::AutoDecRef pyargs(";
- if (func->arguments().isEmpty()) {
+ if (func->arguments().isEmpty() || allArgumentsRemoved(func)) {
s << "PyTuple_New(0));" << endl;
} else {
QStringList argConversions;
@@ -3442,7 +3453,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m
s << INDENT << "Shiboken::ObjectType::setDestructorFunction(&" << cpythonTypeName(metaClass) << ", &Shiboken::callCppDestructor<" << dtorClassName << " >);" << endl;
}
- s << INDENT << "Py_INCREF((PyObject*)&" << pyTypeName << "); //Incref due the 'PyModule_AddObject' steals the reference." << endl;
+ s << INDENT << "Py_INCREF((PyObject*)&" << pyTypeName << "); //Incref due the 'PyModule_AddObject' steals the reference." << endl;
s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << pyTypeName << ") < 0)" << endl;
s << INDENT << INDENT << "return;" << endl << endl;
diff --git a/tests/libsample/virtualmethods.cpp b/tests/libsample/virtualmethods.cpp
index 63c1c8711..bd47dbb0e 100644
--- a/tests/libsample/virtualmethods.cpp
+++ b/tests/libsample/virtualmethods.cpp
@@ -42,3 +42,12 @@ VirtualMethods::createStr(const char* text, Str*& ret)
return true;
}
+void
+VirtualMethods::getMargins(int* left, int* top, int* right, int* bottom) const
+{
+ *left = m_left;
+ *top = m_top;
+ *right = m_right;
+ *bottom = m_bottom;
+}
+
diff --git a/tests/libsample/virtualmethods.h b/tests/libsample/virtualmethods.h
index dc5db49f4..38a421d30 100644
--- a/tests/libsample/virtualmethods.h
+++ b/tests/libsample/virtualmethods.h
@@ -33,7 +33,10 @@
class LIBSAMPLE_API VirtualMethods
{
public:
- VirtualMethods(Str name = "VirtualMethods") : m_name(name) {}
+ VirtualMethods(Str name = "VirtualMethods") : m_name(name)
+ {
+ m_left = m_top = m_right = m_bottom = 0;
+ }
virtual ~VirtualMethods() {}
virtual double virtualMethod0(Point pt, int val, Complex cpx, bool b);
@@ -81,9 +84,25 @@ public:
std::list<Str> callStrListToStdList(const StrList& strList) { return strListToStdList(strList); }
virtual std::list<Str> strListToStdList(const StrList& strList ) { return strList; }
+ void setMargins(int left, int top, int right, int bottom)
+ {
+ m_left = left;
+ m_top = top;
+ m_right = right;
+ m_bottom = bottom;
+ }
+ virtual void getMargins(int* left, int* top, int* right, int* bottom) const;
+ void callGetMargins(int* left, int* top, int* right, int* bottom) const
+ {
+ getMargins(left, top, right, bottom);
+ }
private:
Str m_name;
+ int m_left;
+ int m_top;
+ int m_right;
+ int m_bottom;
};
class LIBSAMPLE_API VirtualDaughter : public VirtualMethods
diff --git a/tests/samplebinding/modifiedvirtualmethods_test.py b/tests/samplebinding/modifiedvirtualmethods_test.py
index 208677695..8580fedd5 100644
--- a/tests/samplebinding/modifiedvirtualmethods_test.py
+++ b/tests/samplebinding/modifiedvirtualmethods_test.py
@@ -26,10 +26,9 @@
'''Test cases for modified virtual methods.'''
-import sys
import unittest
-from sample import VirtualMethods, Point, Str
+from sample import VirtualMethods, Str
class ExtendedVirtualMethods(VirtualMethods):
def __init__(self):
@@ -75,6 +74,9 @@ class ExtendedVirtualMethods(VirtualMethods):
def callMe(self):
self.callMe_called += 1
+ def getMargins(self):
+ return tuple([m*2 for m in VirtualMethods.getMargins(self)])
+
class VirtualMethodsTest(unittest.TestCase):
'''Test case for modified virtual methods.'''
@@ -108,7 +110,8 @@ class VirtualMethodsTest(unittest.TestCase):
self.assertFalse(self.evm.sum0_called)
def testModifiedVirtualMethod1(self):
- '''Virtual method with three arguments and the last one changed to have the default value set to 1000.'''
+ '''Virtual method with three arguments and the last one
+ changed to have the default value set to 1000.'''
a0, a1, a2 = 2, 3, 5
result0 = self.vm.sum1(a0, a1)
self.assertEqual(result0, a0 + a1 + 1000)
@@ -117,7 +120,8 @@ class VirtualMethodsTest(unittest.TestCase):
self.assertEqual(result1, result2)
def testReimplementedModifiedVirtualMethod1(self):
- '''Override of the virtual method with three arguments and the last one changed to have the default value set to 1000.'''
+ '''Override of the virtual method with three arguments and
+ the last one changed to have the default value set to 1000.'''
a0, a1 = 2, 3
result0 = self.vm.sum1(a0, a1)
result1 = self.evm.callSum1(a0, a1, 1000)
@@ -125,7 +129,8 @@ class VirtualMethodsTest(unittest.TestCase):
self.assert_(self.evm.sum1_called)
def testModifiedVirtualMethod2(self):
- '''Virtual method originally with three arguments, the last one was removed and the default value set to 2000.'''
+ '''Virtual method originally with three arguments, the last
+ one was removed and the default value set to 2000.'''
a0, a1 = 1, 2
result0 = self.vm.sum2(a0, a1)
self.assertEqual(result0, a0 + a1 + 2000)
@@ -135,7 +140,8 @@ class VirtualMethodsTest(unittest.TestCase):
self.assertRaises(TypeError, self.vm.sum2, 1, 2, 3)
def testReimplementedModifiedVirtualMethod2(self):
- '''Override of the virtual method originally with three arguments, the last one was removed and the default value set to 2000.'''
+ '''Override of the virtual method originally with three arguments,
+ the last one was removed and the default value set to 2000.'''
a0, a1 = 1, 2
ignored = 54321
result0 = self.vm.sum2(a0, a1)
@@ -144,8 +150,9 @@ class VirtualMethodsTest(unittest.TestCase):
self.assert_(self.evm.sum2_called)
def testModifiedVirtualMethod3(self):
- '''Virtual method originally with three arguments have the second one removed and replaced
- by custom code that replaces it by the sum of the first and the last arguments.'''
+ '''Virtual method originally with three arguments have the second
+ one removed and replaced by custom code that replaces it by the sum
+ of the first and the last arguments.'''
a0, a1 = 1, 2
result0 = self.vm.sum3(a0, a1)
self.assertEqual(result0, a0 + (a0 + a1) + a1)
@@ -156,8 +163,9 @@ class VirtualMethodsTest(unittest.TestCase):
self.assertRaises(TypeError, self.vm.sum3, 1, 2, 3)
def testReimplementedModifiedVirtualMethod3(self):
- '''Override of the virtual method originally with three arguments have the second one removed and replaced
- by custom code that replaces it by the sum of the first and the last arguments.'''
+ '''Override of the virtual method originally with three arguments
+ have the second one removed and replaced by custom code that
+ replaces it by the sum of the first and the last arguments.'''
a0, a1 = 1, 2
ignored = 54321
result0 = self.vm.sum3(a0, a1)
@@ -166,8 +174,8 @@ class VirtualMethodsTest(unittest.TestCase):
self.assert_(self.evm.sum3_called)
def testModifiedVirtualMethod4(self):
- '''Virtual method originally with three arguments, the last one was removed and the default
- value set to 3000.'''
+ '''Virtual method originally with three arguments, the
+ last one was removed and the default value set to 3000.'''
a0, a1 = 1, 2
default_value = 3000
result0 = self.vm.sum4(a0, a1)
@@ -178,11 +186,13 @@ class VirtualMethodsTest(unittest.TestCase):
self.assertRaises(TypeError, self.vm.sum4, 1, 2, 3)
def testReimplementedModifiedVirtualMethod4(self):
- '''Override of the virtual method originally with three arguments, the last one was removed
- and the default value set to 3000. The method was modified with code injection on the binding
- override (the one that receives calls from C++ with the original signature and forwards it
- to Python overrides) that subtracts the value of the second argument (removed in Python)
- from the value of the first before sending them to Python.'''
+ '''Override of the virtual method originally with three arguments,
+ the last one was removed and the default value set to 3000.
+ The method was modified with code injection on the binding override
+ (the one that receives calls from C++ with the original signature
+ and forwards it to Python overrides) that subtracts the value of the
+ second argument (removed in Python) from the value of the first
+ before sending them to Python.'''
a0, a1 = 1, 2
removed_arg_value = 2011
default_value = 3000
@@ -191,7 +201,8 @@ class VirtualMethodsTest(unittest.TestCase):
self.assert_(self.evm.sum4_called)
def testOverridenMethodResultModification(self):
- '''Injected code modifies the result of a call to a virtual method overriden in Python.'''
+ '''Injected code modifies the result of a call to a virtual
+ method overridden in Python.'''
orig_name = self.vm.callName()
self.assertEqual(orig_name, 'VirtualMethods')
name = self.evm.callName()
@@ -205,6 +216,28 @@ class VirtualMethodsTest(unittest.TestCase):
self.evm.callCallMe()
self.assertEqual(self.evm.callMe_called, 1)
+ def testAllArgumentsRemoved(self):
+ values = (10, 20, 30, 40)
+ self.vm.setMargins(*values)
+ self.assertEquals(self.vm.getMargins(), values)
+
+ def testAllArgumentsRemovedCallVirtual(self):
+ values = (10, 20, 30, 40)
+ self.vm.setMargins(*values)
+ self.assertEquals(self.vm.callGetMargins(), values)
+
+ def testExtendedAllArgumentsRemoved(self):
+ values = (10, 20, 30, 40)
+ self.evm.setMargins(*values)
+ double = tuple([m*2 for m in values])
+ self.assertEquals(self.evm.getMargins(), double)
+
+ def testExtendedAllArgumentsRemovedCallVirtual(self):
+ values = (10, 20, 30, 40)
+ self.evm.setMargins(*values)
+ double = tuple([m*2 for m in values])
+ self.assertEquals(self.evm.callGetMargins(), double)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml
index a3e4c830b..56bfcfee3 100644
--- a/tests/samplebinding/typesystem_sample.xml
+++ b/tests/samplebinding/typesystem_sample.xml
@@ -775,6 +775,74 @@
PyTuple_SET_ITEM(%PYARG_0, 1, _item_);
</inject-code>
</modify-function>
+ <template name="fix_int*,int*,int*,int*">
+ int a0, a1, a2, a3;
+ PyThreadState* _save = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS
+ %CPPSELF->::%TYPE::%FUNCTION_NAME(&amp;a0, &amp;a1, &amp;a2, &amp;a3);
+ PyEval_RestoreThread(_save); // Py_END_ALLOW_THREADS
+ %PYARG_0 = Shiboken::makeTuple(a0, a1, a2, a3);
+ </template>
+ <template name="fix_native_return_int*,int*,int*,int*">
+ PyObject* _obj = %PYARG_0.object();
+ if (!PySequence_Check(_obj)
+ || PySequence_Fast_GET_SIZE(_obj) != 4
+ || !SbkNumber_Check(PySequence_Fast_GET_ITEM(_obj, 0))
+ || !SbkNumber_Check(PySequence_Fast_GET_ITEM(_obj, 1))
+ || !SbkNumber_Check(PySequence_Fast_GET_ITEM(_obj, 2))
+ || !SbkNumber_Check(PySequence_Fast_GET_ITEM(_obj, 3))) {
+ PyErr_SetString(PyExc_TypeError, "Sequence of 4 numbers expected");
+ } else {
+ *%1 = %CONVERTTOCPP[int](PySequence_Fast_GET_ITEM(_obj, 0));
+ *%2 = %CONVERTTOCPP[int](PySequence_Fast_GET_ITEM(_obj, 1));
+ *%3 = %CONVERTTOCPP[int](PySequence_Fast_GET_ITEM(_obj, 2));
+ *%4 = %CONVERTTOCPP[int](PySequence_Fast_GET_ITEM(_obj, 3));
+ }
+ </template>
+ <modify-function signature="getMargins(int*,int*,int*,int*)const">
+ <modify-argument index="0">
+ <replace-type modified-type="PyObject" />
+ </modify-argument>
+ <modify-argument index="1">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="2">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="3">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="4">
+ <remove-argument/>
+ <remove-default-expression/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ <insert-template name="fix_int*,int*,int*,int*"/>
+ </inject-code>
+ <inject-code class="native" position="end">
+ <insert-template name="fix_native_return_int*,int*,int*,int*"/>
+ </inject-code>
+ </modify-function>
+ <modify-function signature="callGetMargins(int*,int*,int*,int*)const">
+ <modify-argument index="0">
+ <replace-type modified-type="PyObject" />
+ </modify-argument>
+ <modify-argument index="1">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="2">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="3">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="4">
+ <remove-argument/>
+ <remove-default-expression/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ <insert-template name="fix_int*,int*,int*,int*"/>
+ </inject-code>
+ </modify-function>
</value-type>
<value-type name="VirtualDaughter" />