diff options
author | Marcelo Lira <marcelo.lira@openbossa.org> | 2011-04-06 18:58:18 -0300 |
---|---|---|
committer | Hugo Parente Lima <hugo.pl@gmail.com> | 2012-03-08 16:15:20 -0300 |
commit | f107f41c2b99517133ac4d2d624e8ee61cac2bb2 (patch) | |
tree | 5a5f4961c1189468c488c81e542b923937bd9316 | |
parent | 8c506130849194b0f7838a7920b5f7cc94bfe619 (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.cpp | 15 | ||||
-rw-r--r-- | tests/libsample/virtualmethods.cpp | 9 | ||||
-rw-r--r-- | tests/libsample/virtualmethods.h | 21 | ||||
-rw-r--r-- | tests/samplebinding/modifiedvirtualmethods_test.py | 69 | ||||
-rw-r--r-- | tests/samplebinding/typesystem_sample.xml | 68 |
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(&a0, &a1, &a2, &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" /> |