From 764498b3d033a1c947a40dc1b2237e81b674992b Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Mon, 11 Sep 2017 13:36:35 +0200 Subject: Implement proper void pointer (void*) support This change introduces a new type into the shiboken2 module which is imported by calling "import PySide2.support.VoidPtr". The type takes care of conversions from / to void* values in function signatures. Creating an instance can be done by passing either a shiboken wrapped object, or an integer representing an address, or a python object that implements the buffer interface. For example, this is useful for passing numpy arrays to C OpenGL functions that take void* parameters. First you convert the array into a bytestring (using numpy.array.tobytes(), then you instantiate a VoidPtr from that bytestring, and finally you pass it along to a GL function. One corner case that is currently not supported is void** parameters. Change-Id: I01e291d6856cb6bd8b5175adc3ead6b728036535 Reviewed-by: Christian Tismer --- sources/pyside2/PySide2/support/__init__.py | 10 +- .../pyside2/tests/QtXml/qxmlsimplereader_test.py | 1 - sources/shiboken2/libshiboken/CMakeLists.txt | 2 + sources/shiboken2/libshiboken/basewrapper.cpp | 3 + sources/shiboken2/libshiboken/sbkconverter.cpp | 3 +- sources/shiboken2/libshiboken/sbkconverter_p.h | 25 -- sources/shiboken2/libshiboken/voidptr.cpp | 452 +++++++++++++++++++++ sources/shiboken2/libshiboken/voidptr.h | 65 +++ sources/shiboken2/shibokenmodule/CMakeLists.txt | 5 + .../shibokenmodule/typesystem_shiboken.xml | 3 + sources/shiboken2/tests/libsample/voidholder.h | 4 + .../tests/samplebinding/typesystem_sample.xml | 12 +- .../tests/samplebinding/voidholder_test.py | 20 +- 13 files changed, 556 insertions(+), 49 deletions(-) create mode 100644 sources/shiboken2/libshiboken/voidptr.cpp create mode 100644 sources/shiboken2/libshiboken/voidptr.h diff --git a/sources/pyside2/PySide2/support/__init__.py b/sources/pyside2/PySide2/support/__init__.py index b2085d892..6a6d267b6 100644 --- a/sources/pyside2/PySide2/support/__init__.py +++ b/sources/pyside2/PySide2/support/__init__.py @@ -37,4 +37,12 @@ ## ############################################################################# -# This file has intentionally no content. +# Import VoidPtr type to expose it under PySide2.support.VoidPtr +try: + # The normal import statement when PySide2 is installed. + from PySide2.shiboken2 import VoidPtr +except ImportError: + # When running make test in shiboken build dir, or when running testrunner.py, + # shiboken2 is not part of the PySide2 module, so it needs to be imported as a standalone + # module. + from shiboken2 import VoidPtr diff --git a/sources/pyside2/tests/QtXml/qxmlsimplereader_test.py b/sources/pyside2/tests/QtXml/qxmlsimplereader_test.py index d5df57953..108fc9b86 100644 --- a/sources/pyside2/tests/QtXml/qxmlsimplereader_test.py +++ b/sources/pyside2/tests/QtXml/qxmlsimplereader_test.py @@ -57,7 +57,6 @@ class QXmlSimpleReaderTest(unittest.TestCase): reader = QXmlSimpleReader() prop, ok = reader.property('foo') self.assertEqual((prop, ok), (None, False)) - reader.setProperty('foo', 'Something') if __name__ == '__main__': unittest.main() diff --git a/sources/shiboken2/libshiboken/CMakeLists.txt b/sources/shiboken2/libshiboken/CMakeLists.txt index d2553369b..6f7e4b463 100644 --- a/sources/shiboken2/libshiboken/CMakeLists.txt +++ b/sources/shiboken2/libshiboken/CMakeLists.txt @@ -38,6 +38,7 @@ threadstatesaver.cpp shibokenbuffer.cpp signature.cpp qapp_macro.cpp +voidptr.cpp ) include_directories(${CMAKE_CURRENT_SOURCE_DIR} @@ -70,6 +71,7 @@ install(FILES sbkpython.h signature.h qapp_macro.h + voidptr.h "${CMAKE_CURRENT_BINARY_DIR}/sbkversion.h" DESTINATION include/shiboken2${shiboken2_SUFFIX}) install(TARGETS libshiboken EXPORT shiboken2 diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp index ff9158d66..270a5df94 100644 --- a/sources/shiboken2/libshiboken/basewrapper.cpp +++ b/sources/shiboken2/libshiboken/basewrapper.cpp @@ -54,6 +54,7 @@ #include "threadstatesaver.h" #include "signature.h" #include "qapp_macro.h" +#include "voidptr.h" namespace { void _destroyParentInfo(SbkObject* obj, bool keepReference); @@ -567,6 +568,8 @@ void init() if (PyType_Ready(reinterpret_cast(&SbkObject_Type)) < 0) Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapper type."); + VoidPtr::init(); + shibokenAlreadInitialised = true; } diff --git a/sources/shiboken2/libshiboken/sbkconverter.cpp b/sources/shiboken2/libshiboken/sbkconverter.cpp index ebd586a5e..0949d803d 100644 --- a/sources/shiboken2/libshiboken/sbkconverter.cpp +++ b/sources/shiboken2/libshiboken/sbkconverter.cpp @@ -45,6 +45,7 @@ #include "autodecref.h" #include "sbkdbg.h" #include "helper.h" +#include "voidptr.h" static SbkConverter** PrimitiveTypeConverters; @@ -73,7 +74,7 @@ void init() Primitive::createConverter(), Primitive::createConverter(), Primitive::createConverter(), - Primitive::createConverter() + VoidPtr::createConverter() }; PrimitiveTypeConverters = primitiveTypeConverters; diff --git a/sources/shiboken2/libshiboken/sbkconverter_p.h b/sources/shiboken2/libshiboken/sbkconverter_p.h index 7efccbab4..110358273 100644 --- a/sources/shiboken2/libshiboken/sbkconverter_p.h +++ b/sources/shiboken2/libshiboken/sbkconverter_p.h @@ -533,29 +533,4 @@ struct Primitive : TwoPrimitive } }; -// Void pointer ---------------------------------------------------------------------------- - -template <> -struct Primitive : OnePrimitive -{ - static PyObject* toPython(const void* cppIn) - { - SbkDbg() << cppIn; - if (!cppIn) - Py_RETURN_NONE; - PyObject *result = reinterpret_cast(const_cast(cppIn)); - Py_INCREF(result); - return result; - } - static void toCpp(PyObject* pyIn, void* cppOut) - { - SbkDbg() << pyIn; - *reinterpret_cast(cppOut) = pyIn; - } - static PythonToCppFunc isConvertible(PyObject *) - { - return toCpp; - } -}; - #endif // SBK_CONVERTER_P_H diff --git a/sources/shiboken2/libshiboken/voidptr.cpp b/sources/shiboken2/libshiboken/voidptr.cpp new file mode 100644 index 000000000..ad2a57358 --- /dev/null +++ b/sources/shiboken2/libshiboken/voidptr.cpp @@ -0,0 +1,452 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "voidptr.h" +#include "sbkconverter.h" +#include "basewrapper.h" +#include "basewrapper_p.h" + +extern "C" +{ + +// Void pointer object definition. +typedef struct { + PyObject_HEAD + void *cptr; + Py_ssize_t size; + bool isWritable; +} SbkVoidPtrObject; + +PyObject *SbkVoidPtrObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + SbkVoidPtrObject *self = reinterpret_cast(type->tp_alloc(type, 0)); + + if (self != 0) { + self->cptr = 0; + self->size = -1; + self->isWritable = false; + } + + return reinterpret_cast(self); +} + +#define SbkVoidPtr_Check(op) (Py_TYPE(op) == &SbkVoidPtrType) + + +int SbkVoidPtrObject_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *addressObject; + Py_ssize_t size = -1; + int isWritable = 0; + SbkVoidPtrObject *sbkSelf = reinterpret_cast(self); + + static const char *kwlist[] = {"address", "size", "writeable", 0}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ni", const_cast(kwlist), + &addressObject, &size, &isWritable)) + return -1; + + // Void pointer. + if (SbkVoidPtr_Check(addressObject)) { + SbkVoidPtrObject *sbkOther = reinterpret_cast(addressObject); + sbkSelf->cptr = sbkOther->cptr; + sbkSelf->size = sbkOther->size; + sbkSelf->isWritable = sbkOther->isWritable > 0 ? true : false; + } + // Shiboken::Object wrapper. + else if (Shiboken::Object::checkType(addressObject)) { + SbkObject *sbkOther = reinterpret_cast(addressObject); + sbkSelf->cptr = sbkOther->d->cptr[0]; + sbkSelf->size = size; + sbkSelf->isWritable = isWritable > 0 ? true : false; + } + // Python buffer interface. + else if (PyObject_CheckBuffer(addressObject)) { + Py_buffer bufferView; + + // Bail out if the object can't provide a simple contiguous buffer. + if (PyObject_GetBuffer(addressObject, &bufferView, PyBUF_SIMPLE) < 0) + return 0; + + sbkSelf->cptr = bufferView.buf; + sbkSelf->size = bufferView.len; + sbkSelf->isWritable = bufferView.readonly > 0 ? false : true; + + // Release the buffer. + PyBuffer_Release(&bufferView); + } + // An integer representing an address. + else { + void *cptr = PyLong_AsVoidPtr(addressObject); + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "Creating a VoidPtr object requires an address of a C++ object, " + "a wrapped Shiboken Object type, " + "an object implementing the Python Buffer interface, " + "or another VoidPtr object."); + return -1; + } + sbkSelf->cptr = cptr; + sbkSelf->size = size; + sbkSelf->isWritable = isWritable > 0 ? true : false; + } + + return 0; +} + +PyObject *SbkVoidPtrObject_richcmp(PyObject *obj1, PyObject *obj2, int op) +{ + PyObject *result = Py_False; + void *cptr1 = 0; + void *cptr2 = 0; + bool validObjects = true; + + if (SbkVoidPtr_Check(obj1)) + cptr1 = reinterpret_cast(obj1)->cptr; + else + validObjects = false; + + if (SbkVoidPtr_Check(obj2)) + cptr2 = reinterpret_cast(obj2)->cptr; + else + validObjects = false; + + if (validObjects) { + switch (op) { + case Py_EQ: if (cptr1 == cptr2) result = Py_True; break; + case Py_NE: if (cptr1 != cptr2) result = Py_True; break; + case Py_LT: break; + case Py_LE: break; + case Py_GT: break; + case Py_GE: break; + } + } + + Py_INCREF(result); + return result; +} + +PyObject *SbkVoidPtrObject_int(PyObject *v) +{ + SbkVoidPtrObject *sbkObject = reinterpret_cast(v); + return PyLong_FromVoidPtr(sbkObject->cptr); +} + +static PyNumberMethods SbkVoidPtrObjectAsNumber = { + /* nb_add */ 0, + /* nb_subtract */ 0, + /* nb_multiply */ 0, +#ifndef IS_PY3K + /* nb_divide */ 0, +#endif + /* nb_remainder */ 0, + /* nb_divmod */ 0, + /* nb_power */ 0, + /* nb_negative */ 0, + /* nb_positive */ 0, + /* nb_absolute */ 0, + /* nb_bool/nb_nonzero */ 0, + /* nb_invert */ 0, + /* nb_lshift */ 0, + /* nb_rshift */ 0, + /* nb_and */ 0, + /* nb_xor */ 0, + /* nb_or */ 0, +#ifndef IS_PY3K + /* nb_coerce */ 0, +#endif + /* nb_int */ SbkVoidPtrObject_int, +#ifdef IS_PY3K + /* nb_reserved */ 0, + /* nb_float */ 0, +#else + /* nb_long */ 0, + /* nb_float */ 0, + /* nb_oct */ 0, + /* nb_hex */ 0, +#endif + + /* nb_inplace_add */ 0, + /* nb_inplace_subtract */ 0, + /* nb_inplace_multiply */ 0, +#ifndef IS_PY3K + /* nb_inplace_div */ 0, +#endif + /* nb_inplace_remainder */ 0, + /* nb_inplace_power */ 0, + /* nb_inplace_lshift */ 0, + /* nb_inplace_rshift */ 0, + /* nb_inplace_and */ 0, + /* nb_inplace_xor */ 0, + /* nb_inplace_or */ 0, + + /* nb_floor_divide */ 0, + /* nb_true_divide */ 0, + /* nb_inplace_floor_divide */ 0, + /* nb_inplace_true_divide */ 0, + + /* nb_index */ 0 +}; + +static Py_ssize_t SbkVoidPtrObject_length(PyObject *v) +{ + SbkVoidPtrObject *sbkObject = reinterpret_cast(v); + if (sbkObject->size < 0) { + PyErr_SetString(PyExc_IndexError, "VoidPtr does not have a size set."); + return -1; + } + + return sbkObject->size; +} + +static PySequenceMethods SbkVoidPtrObjectAsSequence = { + /* sq_length */ SbkVoidPtrObject_length, + /* sq_concat */ 0, + /* sq_repeat */ 0, + /* sq_item */ 0, + /* sq_slice */ 0, + /* sq_ass_item */ 0, + /* sq_ass_slice */ 0, + /* sq_contains */ 0, + /* sq_inplace_concat */ 0, + /* sq_inplace_repeat */ 0 +}; + +static const char trueString[] = "True" ; +static const char falseString[] = "False" ; + +PyObject *SbkVoidPtrObject_repr(PyObject *v) +{ + + + SbkVoidPtrObject *sbkObject = reinterpret_cast(v); + PyObject *s = PyBytes_FromFormat("%s(%p, %zd, %s)", + Py_TYPE(sbkObject)->tp_name, + sbkObject->cptr, + sbkObject->size, + sbkObject->isWritable ? trueString : falseString); + Py_XINCREF(s); + return s; +} + +PyObject *SbkVoidPtrObject_str(PyObject *v) +{ + SbkVoidPtrObject *sbkObject = reinterpret_cast(v); + PyObject *s = PyBytes_FromFormat("%s(Address %p, Size %zd, isWritable %s)", + Py_TYPE(sbkObject)->tp_name, + sbkObject->cptr, + sbkObject->size, + sbkObject->isWritable ? trueString : falseString); + Py_XINCREF(s); + return s; +} + + +// Void pointer type definition. +PyTypeObject SbkVoidPtrType = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) /*ob_size*/ + "VoidPtr", /*tp_name*/ + sizeof(SbkVoidPtrObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + SbkVoidPtrObject_repr, /*tp_repr*/ + &SbkVoidPtrObjectAsNumber, /*tp_as_number*/ + &SbkVoidPtrObjectAsSequence, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + SbkVoidPtrObject_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "Void pointer wrapper", /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + SbkVoidPtrObject_richcmp, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + 0, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + SbkVoidPtrObject_init, /*tp_init*/ + 0, /*tp_alloc*/ + SbkVoidPtrObject_new, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ +#if PY_MAJOR_VERSION > 3 || PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 4 + 0 /*tp_finalize*/ +#endif +}; + +} + + +namespace VoidPtr { + +static int voidPointerInitialized = false; + +void init() +{ + if (PyType_Ready(reinterpret_cast(&SbkVoidPtrType)) < 0) + Py_FatalError("[libshiboken] Failed to initialize Shiboken.VoidPtr type."); + else + voidPointerInitialized = true; +} + +void addVoidPtrToModule(PyObject *module) +{ + if (voidPointerInitialized) { + Py_INCREF(&SbkVoidPtrType); + PyModule_AddObject(module, SbkVoidPtrType.tp_name, + reinterpret_cast(&SbkVoidPtrType)); + } +} + +static PyObject *createVoidPtr(void *cppIn, Py_ssize_t size = 0, bool isWritable = false) +{ + if (!cppIn) + Py_RETURN_NONE; + + SbkVoidPtrObject *result = PyObject_NEW(SbkVoidPtrObject, &SbkVoidPtrType); + if (!result) + Py_RETURN_NONE; + + result->cptr = cppIn; + result->size = size; + result->isWritable = isWritable; + + return reinterpret_cast(result); +} + +static PyObject *toPython(const void *cppIn) +{ + return createVoidPtr(const_cast(cppIn)); +} + +static void VoidPtrToCpp(PyObject *pyIn, void *cppOut) +{ + SbkVoidPtrObject *sbkIn = reinterpret_cast(pyIn); + *reinterpret_cast(cppOut) = sbkIn->cptr; +} + +static PythonToCppFunc VoidPtrToCppIsConvertible(PyObject *pyIn) +{ + return SbkVoidPtr_Check(pyIn) ? VoidPtrToCpp : 0; +} + +static void SbkObjectToCpp(PyObject *pyIn, void *cppOut) +{ + SbkObject *sbkIn = reinterpret_cast(pyIn); + *reinterpret_cast(cppOut) = sbkIn->d->cptr[0]; +} + +static PythonToCppFunc SbkObjectToCppIsConvertible(PyObject *pyIn) +{ + return Shiboken::Object::checkType(pyIn) ? SbkObjectToCpp : 0; +} + +static void PythonBufferToCpp(PyObject *pyIn, void *cppOut) +{ + if (PyObject_CheckBuffer(pyIn)) { + Py_buffer bufferView; + + // Bail out if the object can't provide a simple contiguous buffer. + if (PyObject_GetBuffer(pyIn, &bufferView, PyBUF_SIMPLE) < 0) + return; + + *reinterpret_cast(cppOut) = bufferView.buf; + + // Release the buffer. + PyBuffer_Release(&bufferView); + } +} + +static PythonToCppFunc PythonBufferToCppIsConvertible(PyObject *pyIn) +{ + if (PyObject_CheckBuffer(pyIn)) { + Py_buffer bufferView; + + // Bail out if the object can't provide a simple contiguous buffer. + if (PyObject_GetBuffer(pyIn, &bufferView, PyBUF_SIMPLE) < 0) + return 0; + + // Release the buffer. + PyBuffer_Release(&bufferView); + + return PythonBufferToCpp; + } + return 0; +} + +SbkConverter *createConverter() +{ + SbkConverter *converter = Shiboken::Conversions::createConverter(&SbkVoidPtrType, toPython); + Shiboken::Conversions::addPythonToCppValueConversion(converter, + VoidPtrToCpp, + VoidPtrToCppIsConvertible); + Shiboken::Conversions::addPythonToCppValueConversion(converter, + SbkObjectToCpp, + SbkObjectToCppIsConvertible); + Shiboken::Conversions::addPythonToCppValueConversion(converter, + PythonBufferToCpp, + PythonBufferToCppIsConvertible); + return converter; +} + +} // namespace VoidPtr + + diff --git a/sources/shiboken2/libshiboken/voidptr.h b/sources/shiboken2/libshiboken/voidptr.h new file mode 100644 index 000000000..17dd3a008 --- /dev/null +++ b/sources/shiboken2/libshiboken/voidptr.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef VOIDPTR_H +#define VOIDPTR_H + +#include +#include "shibokenmacros.h" +#include "sbkconverter.h" + +extern "C" +{ + +// Void pointer type declaration. +extern LIBSHIBOKEN_API PyTypeObject SbkVoidPtrType; + +} // extern "C" + +namespace VoidPtr +{ + +void init(); +SbkConverter *createConverter(); +LIBSHIBOKEN_API void addVoidPtrToModule(PyObject *module); + +} + + +#endif // VOIDPTR_H diff --git a/sources/shiboken2/shibokenmodule/CMakeLists.txt b/sources/shiboken2/shibokenmodule/CMakeLists.txt index 31b98132d..f2d7b30f2 100644 --- a/sources/shiboken2/shibokenmodule/CMakeLists.txt +++ b/sources/shiboken2/shibokenmodule/CMakeLists.txt @@ -8,11 +8,16 @@ set(sample_SRC ${CMAKE_CURRENT_BINARY_DIR}/shiboken2/shiboken2_module_wrapper.cpp ) +set(shibokenmodule_TYPESYSTEM +${CMAKE_CURRENT_SOURCE_DIR}/typesystem_shiboken.xml +) + add_custom_command(OUTPUT ${sample_SRC} # Note: shiboken2 is an executable target. By not specifying its explicit # path, CMAKE figures it out, itself! # This fixes an issue with Visual Studio, see https://github.com/PySide/shiboken2/pull/11 COMMAND shiboken2 --project-file=${CMAKE_CURRENT_BINARY_DIR}/shibokenmodule.txt ${GENERATOR_EXTRA_FLAGS} +DEPENDS ${shibokenmodule_TYPESYSTEM} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Running generator for 'shiboken2'..." ) diff --git a/sources/shiboken2/shibokenmodule/typesystem_shiboken.xml b/sources/shiboken2/shibokenmodule/typesystem_shiboken.xml index 18ab52e80..bdb0c9338 100644 --- a/sources/shiboken2/shibokenmodule/typesystem_shiboken.xml +++ b/sources/shiboken2/shibokenmodule/typesystem_shiboken.xml @@ -105,6 +105,7 @@ + // Add __version__ and __version_info__ attributes to the module @@ -116,5 +117,7 @@ PyTuple_SET_ITEM(version, 4, PyInt_FromLong(SHIBOKEN_SERIAL)); PyModule_AddObject(module, "__version_info__", version); PyModule_AddStringConstant(module, "__version__", SHIBOKEN_VERSION); + + VoidPtr::addVoidPtrToModule(module); diff --git a/sources/shiboken2/tests/libsample/voidholder.h b/sources/shiboken2/tests/libsample/voidholder.h index 228bbae3f..6453ce2e7 100644 --- a/sources/shiboken2/tests/libsample/voidholder.h +++ b/sources/shiboken2/tests/libsample/voidholder.h @@ -42,6 +42,10 @@ public: static void* pointerToSomething = new VoidHolder(); return pointerToSomething; } + void *takeVoidPointer(void *item) + { + return item; + } private: void* m_ptr; }; diff --git a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml index 65f989e7e..e4e8f7e22 100644 --- a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml +++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml @@ -2235,17 +2235,7 @@ - - - - - - - %RETURN_TYPE %0 = %TYPE::%FUNCTION_NAME(); - %PYARG_0 = Shiboken::Object::newObject(&SbkObject_Type, %0, false, false); - - - + diff --git a/sources/shiboken2/tests/samplebinding/voidholder_test.py b/sources/shiboken2/tests/samplebinding/voidholder_test.py index cb5cab6e5..6e841684b 100644 --- a/sources/shiboken2/tests/samplebinding/voidholder_test.py +++ b/sources/shiboken2/tests/samplebinding/voidholder_test.py @@ -34,21 +34,29 @@ import unittest from sample import VoidHolder, Point +import shiboken2 as shiboken class VoidHolderTest(unittest.TestCase): '''Test case for void pointer manipulation.''' def testGetVoidPointerFromCppAndPutsOnVoidHolder(self): - '''Passes a void pointer created in C++ and to kept by VoidHolder.''' + '''Passes a void pointer created in C++ to be kept by VoidHolder.''' voidptr = VoidHolder.gimmeMeSomeVoidPointer() voidholder = VoidHolder(voidptr) self.assertEqual(voidptr, voidholder.voidPointer()) + def testPassVoidPointerAsArgument(self): + '''Passes a void pointer created in C++ as an argument to a function.''' + voidptr = VoidHolder.gimmeMeSomeVoidPointer() + voidHolder = VoidHolder() + returnValue = voidHolder.takeVoidPointer(voidptr) + self.assertEqual(returnValue, voidptr) + def testPutRandomObjectInsideVoidHolder(self): '''Passes a C++ pointer for an object created in Python to be kept by VoidHolder.''' obj = Point(1, 2) voidholder = VoidHolder(obj) - self.assertEqual(obj, voidholder.voidPointer()) + self.assertEqual(shiboken.getCppPointer(obj)[0], int(voidholder.voidPointer())) def testGetNoneObjectFromVoidHolder(self): '''A VoidHolder created without parameters returns a NULL pointer @@ -56,14 +64,6 @@ class VoidHolderTest(unittest.TestCase): voidholder = VoidHolder() self.assertEqual(voidholder.voidPointer(), None) - def testPutPythonObjectInsideVoidHolder(self): - '''Passes a native Python object to be kept by VoidHolder.''' - obj = 'Foo' - voidholder = VoidHolder(obj) - self.assertEqual(obj, voidholder.voidPointer()) - - - if __name__ == '__main__': unittest.main() -- cgit v1.2.3