diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp index d5b734f4..f309b7d3 100644 --- a/generator/shibokengenerator.cpp +++ b/generator/shibokengenerator.cpp @@ -966,7 +966,7 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType if (isCppPrimitive(metaType)) { if (isCString(metaType)) - return "SbkString_Check"; + return "Shiboken::String::check"; if (isVoidPointer(metaType)) return "PyObject_Check"; return cpythonCheckFunction(metaType->typeEntry(), genericNumberType); diff --git a/libshiboken/sbkconverter.cpp b/libshiboken/sbkconverter.cpp index b5223cc8..79a2f65f 100644 --- a/libshiboken/sbkconverter.cpp +++ b/libshiboken/sbkconverter.cpp @@ -222,7 +222,7 @@ void nonePythonToCppNullPtr(PyObject*, void* cppOut) void* cppPointer(PyTypeObject* desiredType, SbkObject* pyIn) { assert(pyIn); - SbkObjectType* inType = (SbkObjectType*)pyIn->ob_type; + SbkObjectType* inType = (SbkObjectType*)Py_TYPE(pyIn); if (ObjectType::hasCast(inType)) return ObjectType::cast(inType, pyIn, desiredType); return Object::cppPointer(pyIn, desiredType); diff --git a/libshiboken/sbkconverter_p.h b/libshiboken/sbkconverter_p.h index 8abdc297..d12f1edc 100644 --- a/libshiboken/sbkconverter_p.h +++ b/libshiboken/sbkconverter_p.h @@ -23,10 +23,11 @@ #ifndef SBK_CONVERTER_P_H #define SBK_CONVERTER_P_H -#include +#include "sbkpython.h" +#include "sbkconverter.h" +#include "sbkstring.h" #include #include -#include "sbkconverter.h" #include "sbkdbg.h" @@ -169,10 +170,6 @@ struct TwoPrimitive : OnePrimitive // Integers -------------------------------------------------------------------------------- -// Note: if there wasn't for the old-style classes, a simple PyNumber_Check would suffice. -#define SbkNumber_Check(X) (PyNumber_Check(X) \ - && (!PyInstance_Check(X) || PyObject_HasAttrString(X, "__trunc__"))) - template struct IntPrimitive : TwoPrimitive { @@ -327,11 +324,12 @@ struct CharPrimitive : IntPrimitive { static void toCpp(PyObject* pyIn, void* cppOut) { - *((CHAR*)cppOut) = (CHAR) PyString_AS_STRING(pyIn)[0]; + + *((CHAR*)cppOut) = (CHAR) Shiboken::String::toCString(pyIn)[0]; } static PythonToCppFunc isConvertible(PyObject* pyIn) { - if (PyString_Check(pyIn) && PyString_Size(pyIn) == 1) + if (Shiboken::String::checkChar(pyIn)) return toCpp; return 0; } @@ -361,7 +359,7 @@ template <> struct Primitive : CharPrimitive {}; template <> struct Primitive : CharPrimitive { using CharPrimitive::toPython; static PyObject* toPython(const void* cppIn) { - return PyString_FromFormat("%c", *((const char*)cppIn)); + return Shiboken::String::fromCString((const char*)cppIn, 1); } }; @@ -376,7 +374,7 @@ struct Primitive : TwoPrimitive { if (!cppIn) Py_RETURN_NONE; - return PyString_FromString((const char*)cppIn); + return Shiboken::String::fromCString((const char*)cppIn); } static void toCpp(PyObject* pyIn, void* cppOut) { @@ -390,11 +388,11 @@ struct Primitive : TwoPrimitive } static void otherToCpp(PyObject* pyIn, void* cppOut) { - *((const char**)cppOut) = (const char*) PyString_AsString(pyIn); + *((const char**)cppOut) = (const char*) Shiboken::String::toCString(pyIn); } static PythonToCppFunc isOtherConvertible(PyObject* pyIn) { - if (PyString_Check(pyIn)) + if (Shiboken::String::check(pyIn)) return otherToCpp; return 0; } @@ -405,7 +403,7 @@ struct Primitive : TwoPrimitive { static PyObject* toPython(const void* cppIn) { - return PyString_FromString(((std::string*)cppIn)->c_str()); + return Shiboken::String::fromCString(((std::string*)cppIn)->c_str()); } static void toCpp(PyObject* pyIn, void* cppOut) { @@ -419,11 +417,11 @@ struct Primitive : TwoPrimitive } static void otherToCpp(PyObject* pyIn, void* cppOut) { - *((std::string*)cppOut) = std::string(PyString_AsString(pyIn)); + *((std::string*)cppOut) = Shiboken::String::toCString(pyIn); } static PythonToCppFunc isOtherConvertible(PyObject* pyIn) { - if (PyString_Check(pyIn)) + if (Shiboken::String::check(pyIn)) return otherToCpp; return 0; } diff --git a/libshiboken/sbkpython.h b/libshiboken/sbkpython.h index 850f122f..90df2d4c 100644 --- a/libshiboken/sbkpython.h +++ b/libshiboken/sbkpython.h @@ -41,6 +41,7 @@ #define SBK_NB_BOOL(x) (x).nb_bool #define SBK_PyMethod_New PyMethod_New #define PyInt_AsSsize_t(x) PyLong_AsSsize_t(x) + #define PyString_Type PyUnicode_Type #else // Note: if there wasn't for the old-style classes, only a PyNumber_Check would suffice. diff --git a/libshiboken/sbkstring.cpp b/libshiboken/sbkstring.cpp index de6842dc..9ea5f699 100644 --- a/libshiboken/sbkstring.cpp +++ b/libshiboken/sbkstring.cpp @@ -21,6 +21,7 @@ */ #include "sbkstring.h" +#include "autodecref.h" namespace Shiboken { @@ -68,16 +69,36 @@ PyObject* fromCString(const char* value) #endif } -const char* toCString(PyObject* str) +PyObject* fromCString(const char* value, int len) +{ +#ifdef IS_PY3K + return PyUnicode_FromStringAndSize(value, len); +#else + return PyBytes_FromStringAndSize(value, len); +#endif +} + +const char* toCString(PyObject* str, Py_ssize_t* len) { if (str == Py_None) return NULL; #ifdef IS_PY3K - if (PyUnicode_Check(str)) + if (PyUnicode_Check(str)) { + if (len) { + // We need to encode the unicode string into utf8 to know the size of returned char*. + Shiboken::AutoDecRef uniStr(PyUnicode_AsUTF8String(str)); + *len = PyBytes_GET_SIZE(uniStr.object()); + } + // Return unicode from str instead of uniStr, because the lifetime of the returned pointer + // depends on the lifetime of str. return _PyUnicode_AsString(str); + } #endif - if (PyBytes_Check(str)) + if (PyBytes_Check(str)) { + if (len) + *len = PyBytes_GET_SIZE(str); return PyBytes_AS_STRING(str); + } return 0; } diff --git a/libshiboken/sbkstring.h b/libshiboken/sbkstring.h index d6bc6502..112e7149 100644 --- a/libshiboken/sbkstring.h +++ b/libshiboken/sbkstring.h @@ -41,7 +41,8 @@ namespace String LIBSHIBOKEN_API bool checkChar(PyObject* obj); LIBSHIBOKEN_API bool isConvertible(PyObject* obj); LIBSHIBOKEN_API PyObject* fromCString(const char* value); - LIBSHIBOKEN_API const char* toCString(PyObject* str); + LIBSHIBOKEN_API PyObject* fromCString(const char* value, int len); + LIBSHIBOKEN_API const char* toCString(PyObject* str, Py_ssize_t* len = 0); LIBSHIBOKEN_API bool concat(PyObject** val1, PyObject* val2); LIBSHIBOKEN_API PyObject* fromFormat(const char* format, ...); LIBSHIBOKEN_API PyObject* fromStringAndSize(const char* str, Py_ssize_t size); diff --git a/tests/samplebinding/injectcode_test.py b/tests/samplebinding/injectcode_test.py index a60ef914..52585ec8 100644 --- a/tests/samplebinding/injectcode_test.py +++ b/tests/samplebinding/injectcode_test.py @@ -94,14 +94,12 @@ def testUsageOfTypeSystemCheckVariableOnPrimitiveType(self): '''When the sequence item is convertible to an integer -1 is returned, or -2 if its not convertible.''' ic = InjectCode() values = (1, 2, 3, 4, '5', 6.7) - print values result = ic.arrayMethod(values) - print result + fixedValues = [v for v in values if isinstance(v, int)]\ + [-1 for v in values if isinstance(v, float)]\ + [-2 for v in values if not isinstance(v, int) and not isinstance(v, float)] - print fixedValues - #self.assertEqual(result, sum(fixedValues)) + self.assertEqual(result, sum(fixedValues)) class IntArrayTest(unittest.TestCase): diff --git a/tests/samplebinding/primitivestructpointer_conversions.h b/tests/samplebinding/primitivestructpointer_conversions.h index 9e1d2767..c674215f 100644 --- a/tests/samplebinding/primitivestructpointer_conversions.h +++ b/tests/samplebinding/primitivestructpointer_conversions.h @@ -9,7 +9,11 @@ struct Converter static bool isConvertible(PyObject* pyobj) { +#ifdef IS_PY3K + return PyCapsule_CheckExact(pyobj); +#else return PyCObject_Check(pyobj); +#endif } static inline PyObject* toPython(void* cppobj) @@ -19,12 +23,22 @@ struct Converter static PyObject* toPython(PrimitiveStructPtr cppobj) { +#ifdef IS_PY3K + return PyCapsule_New(cppobj, 0, 0); +#else return PyCObject_FromVoidPtr(cppobj, 0); +#endif } static PrimitiveStructPtr toCpp(PyObject* pyobj) { - return (PrimitiveStructPtr) PyCObject_AsVoidPtr(pyobj); + void* ptr; +#ifdef IS_PY3K + ptr = PyCapsule_GetPointer(pyobj, 0); +#else + ptr = PyCObject_AsVoidPtr(pyobj); +#endif + return (PrimitiveStructPtr) ptr; } }; } diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index f8080167..f823a172 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -68,25 +68,61 @@ - return PyCObject_FromVoidPtr(%in, 0); + if (!%in) + Py_RETURN_NONE; + #ifdef IS_PY3K + return PyCapsule_New(%in, 0, 0); + #else + return PyCObject_FromVoidPtr(%in, 0); + #endif - - %out = (%OUTTYPE)PyCObject_AsVoidPtr(%in); + + %out = 0; + + + void* ptr; + #ifdef IS_PY3K + ptr = PyCapsule_GetPointer(%in, 0); + #else + ptr = PyCObject_AsVoidPtr(%in); + #endif + %out = *((%OUTTYPE*)ptr); + + static bool checkPyCapsuleOrPyCObject(PyObject* pyObj) + { + #ifdef IS_PY3K + return PyCapsule_CheckExact(pyObj); + #else + return PyCObject_Check(pyObj); + #endif + } + + - return PyCObject_FromVoidPtr(&%in, 0); + #ifdef IS_PY3K + return PyCapsule_New(&%in, 0, 0); + #else + return PyCObject_FromVoidPtr(&%in, 0); + #endif - - %out = *((%OUTTYPE*)PyCObject_AsVoidPtr(%in)); + + void* ptr; + #ifdef IS_PY3K + ptr = PyCapsule_GetPointer(%in, 0); + #else + ptr = PyCObject_AsVoidPtr(%in); + #endif + %out = *((%OUTTYPE*)ptr); @@ -118,10 +154,10 @@ - return PyString_FromStringAndSize(%in.cstring(), %in.size()); + return Shiboken::String::fromCString(%in.cstring(), %in.size()); - + const char* str = %CONVERTTOCPP[const char*](%in); %out = %OUTTYPE(str); @@ -1820,14 +1856,16 @@ %out = %OUTTYPE(); - - %out = %OUTTYPE(PyString_AS_STRING(%in), PyString_GET_SIZE(%in)); + + Py_ssize_t len; + const char* str = Shiboken::String::toCString(%in, &len); + %out = %OUTTYPE(str, len); - + @@ -1862,6 +1900,7 @@ + @@ -1909,12 +1948,17 @@ - ByteArray ba(((PyObject*)%PYSELF)->ob_type->tp_name); - ba += '('; - Shiboken::AutoDecRef contents(PyObject_Repr(PyBytes_FromStringAndSize(%CPPSELF.data(), %CPPSELF.size()))); - ba += PyBytes_AS_STRING(contents.object()); - ba += ")"; - %PYARG_0 = PyBytes_FromStringAndSize(ba.data(), ba.size()); + ByteArray b(((PyObject*)%PYSELF)->ob_type->tp_name); + PyObject* aux = Shiboken::String::fromStringAndSize(%CPPSELF.data(), %CPPSELF.size()); + if (PyUnicode_CheckExact(aux)) { + PyObject* tmp = PyUnicode_AsASCIIString(aux); + Py_DECREF(aux); + aux = tmp; + } + b += "('"; + b += ByteArray(PyBytes_AS_STRING(aux), PyBytes_GET_SIZE(aux)); + b += "')"; + %PYARG_0 = Shiboken::String::fromStringAndSize(b.data(), b.size());