Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6')
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp20
-rw-r--r--sources/shiboken6/ApiExtractor/apiextractor.cpp1
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp20
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp63
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/compilersupport.h8
-rw-r--r--sources/shiboken6/ApiExtractor/customconversion.cpp3
-rw-r--r--sources/shiboken6/ApiExtractor/parser/typeinfo.cpp38
-rw-r--r--sources/shiboken6/ApiExtractor/parser/typeinfo.h5
-rw-r--r--sources/shiboken6/ApiExtractor/smartpointertypeentry.h5
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem.cpp19
-rw-r--r--sources/shiboken6/ApiExtractor/typesystemparser.cpp8
-rw-r--r--sources/shiboken6/cmake/ShibokenHelpers.cmake25
-rw-r--r--sources/shiboken6/doc/typesystem_conversionrule.rst15
-rw-r--r--sources/shiboken6/doc/typesystem_converters.rst36
-rw-r--r--sources/shiboken6/doc/typesystem_specifying_types.rst6
-rw-r--r--sources/shiboken6/doc/typesystem_variables.rst2
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp44
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.h8
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp11
-rw-r--r--sources/shiboken6/generator/shiboken/headergenerator.cpp6
-rw-r--r--sources/shiboken6/libshiboken/basewrapper.cpp76
-rw-r--r--sources/shiboken6/libshiboken/basewrapper.h5
-rw-r--r--sources/shiboken6/libshiboken/bindingmanager.cpp15
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py2
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py4
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py1
-rw-r--r--sources/shiboken6/tests/libsample/bucket.cpp14
-rw-r--r--sources/shiboken6/tests/libsample/bucket.h6
-rw-r--r--sources/shiboken6/tests/libsample/samplenamespace.cpp9
-rw-r--r--sources/shiboken6/tests/libsample/samplenamespace.h4
-rw-r--r--sources/shiboken6/tests/samplebinding/sample_test.py7
-rw-r--r--sources/shiboken6/tests/samplebinding/typesystem_sample.xml19
32 files changed, 356 insertions, 149 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
index 27570ec4f..fb5399baa 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
@@ -2664,7 +2664,7 @@ std::optional<AbstractMetaType>
qsizetype i = d ? d->m_scopes.size() - 1 : -1;
while (i >= 0) {
typeInfo = TypeInfo::resolveType(_typei, d->m_scopes.at(i--));
- if (typeInfo.qualifiedName().join(u"::"_s) != _typei.qualifiedName().join(u"::"_s))
+ if (typeInfo.qualifiedName() != _typei.qualifiedName())
break;
}
@@ -2757,12 +2757,22 @@ std::optional<AbstractMetaType>
// 4. Special case QFlags (include instantiation in name)
if (qualifiedName == u"QFlags") {
- qualifiedName = typeInfo.toString();
+ qualifiedName = typeInfo.qualifiedInstantationName();
typeInfo.clearInstantiations();
}
TypeEntryCList types = findTypeEntries(qualifiedName, name, flags,
currentClass, d, errorMessageIn);
+ if (types.isEmpty() && !typeInfo.instantiations().isEmpty()) {
+ // Allow for specifying template specializations as primitive types
+ // with converters ('std::optional<int>' or similar).
+ auto pt = TypeDatabase::instance()->findPrimitiveType(typeInfo.qualifiedInstantationName());
+ if (pt) {
+ types.append(pt);
+ typeInfo.clearInstantiations();
+ }
+ }
+
if (!flags.testFlag(AbstractMetaBuilder::TemplateArgument)) {
// Avoid clashes between QByteArray and enum value QMetaType::QByteArray
// unless we are looking for template arguments.
@@ -2796,7 +2806,7 @@ std::optional<AbstractMetaType>
// For non-type template parameters, create a dummy type entry on the fly
// as is done for classes.
if (!targType.has_value()) {
- const QString value = ti.qualifiedName().join(u"::"_s);
+ const QString value = ti.qualifiedNameString();
if (isNumber(value)) {
auto module = typeSystemTypeEntry(type);
TypeDatabase::instance()->addConstantValueTypeEntry(value, module);
@@ -3082,7 +3092,7 @@ AbstractMetaClassPtr
QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join(u"::"_s) + u"::"_s : QString();
QString completeName = prefix + name;
const TypeInfo parsed = TypeParser::parse(completeName, &errorMessage);
- QString qualifiedName = parsed.qualifiedName().join(u"::"_s);
+ QString qualifiedName = parsed.qualifiedNameString();
if (qualifiedName.isEmpty()) {
qWarning().noquote().nospace() << "Unable to parse type \"" << completeName
<< "\" while looking for template \"" << name << "\": " << errorMessage;
@@ -3196,7 +3206,7 @@ static std::optional<AbstractMetaType>
const AbstractMetaClassCPtr &templateClass,
const TypeInfo &info, QString *errorMessage)
{
- QString typeName = info.qualifiedName().join("::"_L1);
+ QString typeName = info.qualifiedNameString();
TypeDatabase *typeDb = TypeDatabase::instance();
TypeEntryPtr t;
// Check for a non-type template integer parameter, that is, for a base
diff --git a/sources/shiboken6/ApiExtractor/apiextractor.cpp b/sources/shiboken6/ApiExtractor/apiextractor.cpp
index 90f4f5dd9..38dedfd14 100644
--- a/sources/shiboken6/ApiExtractor/apiextractor.cpp
+++ b/sources/shiboken6/ApiExtractor/apiextractor.cpp
@@ -370,6 +370,7 @@ bool ApiExtractorPrivate::runHelper(ApiExtractorFlags flags)
bool addCompilerSupportArguments = true;
if (clangOptionsSize > 0) {
+ clang::setTargetTriple(m_clangOptions);
qsizetype i = 0;
if (m_clangOptions.at(i) == u"-") {
++i;
diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp
index 54a1a2c8b..747937ede 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp
+++ b/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp
@@ -275,6 +275,24 @@ static CXTranslationUnit createTranslationUnit(CXIndex index,
return tu;
}
+static void setupTarget(CXTranslationUnit translationUnit)
+{
+ const CXTargetInfo targetInfo = clang_getTranslationUnitTargetInfo(translationUnit);
+ const auto tripleCS = clang_TargetInfo_getTriple(targetInfo);
+ clang::setPointerSize(clang_TargetInfo_getPointerWidth(targetInfo));
+ clang::setTargetTriple(QString::fromUtf8(clang_getCString(tripleCS)));
+ clang_disposeString(tripleCS);
+
+ QString message;
+ {
+ QTextStream str(&message);
+ str << "CLANG v" << CINDEX_VERSION_MAJOR << '.' << CINDEX_VERSION_MINOR
+ << " targeting \"" << targetTriple() << "\", " << pointerSize() << "bit.";
+ }
+ qCInfo(lcShiboken, "%s", qPrintable(message));
+ ReportHandler::addGeneralMessage(message + u'\n');
+}
+
/* clangFlags are flags to clang_parseTranslationUnit2() such as
* CXTranslationUnit_KeepGoing (from CINDEX_VERSION_MAJOR/CINDEX_VERSION_MINOR 0.35)
*/
@@ -295,6 +313,8 @@ bool parse(const QByteArrayList &clangArgs, bool addCompilerSupportArguments,
if (!translationUnit)
return false;
+ setupTarget(translationUnit);
+
CXCursor rootCursor = clang_getTranslationUnitCursor(translationUnit);
clang_visitChildren(rootCursor, visitorCallback, reinterpret_cast<CXClientData>(&bv));
diff --git a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp
index ed8057b62..4d93a084f 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp
+++ b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp
@@ -59,6 +59,9 @@ bool setCompiler(const QString &name)
QString _compilerPath; // Pre-defined compiler path (from command line)
+static unsigned _pointerSize = QT_POINTER_SIZE * 8;
+static QString _targetTriple;
+
const QString &compilerPath()
{
return _compilerPath;
@@ -153,14 +156,15 @@ static void filterHomebrewHeaderPaths(HeaderPaths &headerPaths)
if (homebrewPrefix.isEmpty())
return;
- qCInfo(lcShiboken) << "Found HOMEBREW_OPT with value:" << homebrewPrefix
- << "Assuming homebrew build environment.";
+ ReportHandler::addGeneralMessage("Found HOMEBREW_OPT with value:"_L1
+ + QString::fromUtf8(homebrewPrefix)
+ + "\nAssuming homebrew build environment."_L1);
HeaderPaths::iterator it = headerPaths.begin();
while (it != headerPaths.end()) {
if (it->path.startsWith(homebrewPrefix)) {
- qCInfo(lcShiboken) << "Filtering out homebrew include path: "
- << it->path;
+ ReportHandler::addGeneralMessage("Filtering out homebrew include path: "_L1
+ + QString::fromUtf8(it->path));
it = headerPaths.erase(it);
} else {
++it;
@@ -186,12 +190,6 @@ static HeaderPaths gppInternalIncludePaths(const QString &compiler)
const QByteArrayList stdErrLines = stdErr.split('\n');
bool isIncludeDir = false;
- if (ReportHandler::isDebug(ReportHandler::MediumDebug))
- qCInfo(lcShiboken()).noquote().nospace()
- << "gppInternalIncludePaths:\n compiler: " << compiler
- << "\n stdOut: " << stdOut
- << "\n stdErr: " << stdErr;
-
for (const QByteArray &line : stdErrLines) {
if (isIncludeDir) {
if (line.startsWith(QByteArrayLiteral("End of search list"))) {
@@ -212,6 +210,17 @@ static HeaderPaths gppInternalIncludePaths(const QString &compiler)
if (platform() == Platform::macOS)
filterHomebrewHeaderPaths(result);
+ QString message;
+ {
+ QTextStream str(&message);
+ str << "gppInternalIncludePaths:\n compiler: " << compiler << '\n';
+ for (const auto &h : result)
+ str << " " << h.path << '\n';
+ if (ReportHandler::isDebug(ReportHandler::MediumDebug))
+ str << " stdOut: " << stdOut << "\n stdErr: " << stdErr;
+ }
+ ReportHandler::addGeneralMessage(message);
+
return result;
}
@@ -365,11 +374,10 @@ static void appendClangBuiltinIncludes(HeaderPaths *p)
"(neither by checking the environment variables LLVM_INSTALL_DIR, CLANG_INSTALL_DIR "
" nor running llvm-config). This may lead to parse errors.");
} else {
- qCInfo(lcShiboken, "CLANG v%d.%d, builtins includes directory: %s",
- CINDEX_VERSION_MAJOR, CINDEX_VERSION_MINOR,
- qPrintable(clangBuiltinIncludesDir));
p->append(HeaderPath{QFile::encodeName(clangBuiltinIncludesDir),
HeaderType::System});
+ ReportHandler::addGeneralMessage("CLANG builtins includes directory: "_L1
+ + clangBuiltinIncludesDir);
}
}
@@ -451,4 +459,33 @@ LanguageLevel languageLevelFromOption(const char *o)
return LanguageLevel::Default;
}
+unsigned pointerSize()
+{
+ return _pointerSize;
+}
+
+void setPointerSize(unsigned ps)
+{
+ _pointerSize = ps;
+}
+
+QString targetTriple()
+{
+ return _targetTriple;
+
+}
+void setTargetTriple(const QString &t)
+{
+ _targetTriple = t;
+}
+
+void setTargetTriple(const QStringList &clangOptions)
+{
+ static constexpr auto targetOption = "--target="_L1;
+ auto targetOptionPred = [](const QString &o) { return o.startsWith(targetOption); };
+ const auto it = std::find_if(clangOptions.cbegin(), clangOptions.cend(), targetOptionPred);
+ if (it != clangOptions.cend())
+ _targetTriple = it->sliced(targetOption.size());
+}
+
} // namespace clang
diff --git a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h
index 1fa980998..0e12ca137 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h
+++ b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h
@@ -51,6 +51,14 @@ void setCompilerPath(const QString &name);
Platform platform();
bool setPlatform(const QString &name);
+
+unsigned pointerSize(); // (bit)
+void setPointerSize(unsigned ps); // Set by parser
+
+QString targetTriple();
+void setTargetTriple(const QStringList &clangOptions); // Set from cmd line before parsing
+void setTargetTriple(const QString &t); // Updated by clang parser while parsing
+
} // namespace clang
#endif // COMPILERSUPPORT_H
diff --git a/sources/shiboken6/ApiExtractor/customconversion.cpp b/sources/shiboken6/ApiExtractor/customconversion.cpp
index 4cfd1b974..7b65bcf3a 100644
--- a/sources/shiboken6/ApiExtractor/customconversion.cpp
+++ b/sources/shiboken6/ApiExtractor/customconversion.cpp
@@ -5,6 +5,7 @@
#include "containertypeentry.h"
#include "customtypenentry.h"
#include "primitivetypeentry.h"
+#include "smartpointertypeentry.h"
#include "valuetypeentry.h"
#include <QtCore/qdebug.h>
@@ -139,6 +140,8 @@ CustomConversionPtr CustomConversion::getCustomConversion(const TypeEntryCPtr &t
return std::static_pointer_cast<const ContainerTypeEntry>(type)->customConversion();
if (type->isValue())
return std::static_pointer_cast<const ValueTypeEntry>(type)->customConversion();
+ if (type->isSmartPointer())
+ return std::static_pointer_cast<const SmartPointerTypeEntry>(type)->customConversion();
return {};
}
diff --git a/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp b/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp
index 845a0f916..93627e6d5 100644
--- a/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp
+++ b/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp
@@ -110,6 +110,28 @@ QStringList TypeInfo::qualifiedName() const
return d->m_qualifiedName;
}
+QString TypeInfo::qualifiedNameString() const
+{
+ return d->m_qualifiedName.join("::"_L1);
+}
+
+QString TypeInfo::qualifiedInstantationName() const
+{
+ QString result = qualifiedNameString();
+ if (const auto instantiationCount = d->m_instantiations.size()) {
+ result += u'<';
+ for (qsizetype i = 0; i < instantiationCount; ++i) {
+ if (i)
+ result += ", "_L1;
+ result += d->m_instantiations.at(i).toString();
+ }
+ if (result.endsWith(u'>'))
+ result += u' ';
+ result += u'>';
+ }
+ return result;
+}
+
void TypeInfo::setQualifiedName(const QStringList &qualified_name)
{
if (d->m_qualifiedName != qualified_name)
@@ -300,7 +322,7 @@ TypeInfo TypeInfo::resolveType(const CodeModelItem &__item, TypeInfo const &__ty
// typedef struct xcb_connection_t xcb_connection_t;
if (nextItem.get() ==__item.get()) {
std::cerr << "** WARNING Bailing out recursion of " << __FUNCTION__
- << "() on " << qPrintable(__type.qualifiedName().join(u"::"_s))
+ << "() on " << qPrintable(__type.qualifiedNameString())
<< '\n';
return otherType;
}
@@ -385,19 +407,7 @@ QString TypeInfo::toString() const
if (isVolatile())
tmp += u"volatile "_s;
- tmp += d->m_qualifiedName.join(u"::"_s);
-
- if (const auto instantiationCount = d->m_instantiations.size()) {
- tmp += u'<';
- for (qsizetype i = 0; i < instantiationCount; ++i) {
- if (i)
- tmp += u", "_s;
- tmp += d->m_instantiations.at(i).toString();
- }
- if (tmp.endsWith(u'>'))
- tmp += u' ';
- tmp += u'>';
- }
+ tmp += qualifiedInstantationName();
for (Indirection i : d->m_indirections)
tmp.append(indirectionKeyword(i));
diff --git a/sources/shiboken6/ApiExtractor/parser/typeinfo.h b/sources/shiboken6/ApiExtractor/parser/typeinfo.h
index 9cd746e85..6f75b5737 100644
--- a/sources/shiboken6/ApiExtractor/parser/typeinfo.h
+++ b/sources/shiboken6/ApiExtractor/parser/typeinfo.h
@@ -39,6 +39,11 @@ public:
QStringList qualifiedName() const;
void setQualifiedName(const QStringList &qualified_name);
+ // Returns "std::list"
+ QString qualifiedNameString() const;
+ // Returns qualifiedName() with instantions ("std::list<int>")
+ QString qualifiedInstantationName() const;
+
void addName(const QString &);
bool isVoid() const;
diff --git a/sources/shiboken6/ApiExtractor/smartpointertypeentry.h b/sources/shiboken6/ApiExtractor/smartpointertypeentry.h
index d704210f7..7b67647b9 100644
--- a/sources/shiboken6/ApiExtractor/smartpointertypeentry.h
+++ b/sources/shiboken6/ApiExtractor/smartpointertypeentry.h
@@ -5,6 +5,7 @@
#define SMARTPOINTERTYPEENTRY_H
#include "complextypeentry.h"
+#include "customconversion_typedefs.h"
class SmartPointerTypeEntryPrivate;
@@ -51,6 +52,10 @@ public:
QString getTargetName(const AbstractMetaType &metaType) const;
+ bool hasCustomConversion() const;
+ void setCustomConversion(const CustomConversionPtr &customConversion);
+ CustomConversionPtr customConversion() const;
+
#ifndef QT_NO_DEBUG_STREAM
void formatDebug(QDebug &d) const override;
#endif
diff --git a/sources/shiboken6/ApiExtractor/typesystem.cpp b/sources/shiboken6/ApiExtractor/typesystem.cpp
index 0820150f8..46e88291d 100644
--- a/sources/shiboken6/ApiExtractor/typesystem.cpp
+++ b/sources/shiboken6/ApiExtractor/typesystem.cpp
@@ -2154,6 +2154,7 @@ public:
QString m_resetMethod;
SmartPointerTypeEntry::Instantiations m_instantiations;
TypeEntryCList m_excludedInstantiations;
+ CustomConversionPtr m_customConversion;
TypeSystem::SmartPointerType m_smartPointerType;
};
@@ -2306,6 +2307,24 @@ QString SmartPointerTypeEntry::getTargetName(const AbstractMetaType &metaType) c
return fixSmartPointerName(name);
}
+bool SmartPointerTypeEntry::hasCustomConversion() const
+{
+ S_D(const SmartPointerTypeEntry);
+ return bool(d->m_customConversion);
+}
+
+void SmartPointerTypeEntry::setCustomConversion(const CustomConversionPtr &customConversion)
+{
+ S_D(SmartPointerTypeEntry);
+ d->m_customConversion = customConversion;
+}
+
+CustomConversionPtr SmartPointerTypeEntry::customConversion() const
+{
+ S_D(const SmartPointerTypeEntry);
+ return d->m_customConversion;
+}
+
// ----------------- NamespaceTypeEntry
class NamespaceTypeEntryPrivate : public ComplexTypeEntryPrivate
{
diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
index 8b2ad08de..7ae25e48c 100644
--- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp
+++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
@@ -2348,9 +2348,10 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &,
if (topElement != StackElement::ModifyArgument
&& topElement != StackElement::ValueTypeEntry
&& topElement != StackElement::PrimitiveTypeEntry
- && topElement != StackElement::ContainerTypeEntry) {
+ && topElement != StackElement::ContainerTypeEntry
+ && topElement != StackElement::SmartPointerTypeEntry) {
m_error = u"Conversion rules can only be specified for argument modification, "
- "value-type, primitive-type or container-type conversion."_s;
+ "value-type, primitive-type, or container-type or smartpointer-type conversion."_s;
return false;
}
@@ -2415,6 +2416,9 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &,
std::static_pointer_cast<ContainerTypeEntry>(top->entry)->setCustomConversion(customConversion);
else if (top->entry->isValue())
std::static_pointer_cast<ValueTypeEntry>(top->entry)->setCustomConversion(customConversion);
+ else if (top->entry->isSmartPointer())
+ std::static_pointer_cast<SmartPointerTypeEntry>(top->entry)->setCustomConversion(customConversion);
+
customConversionsForReview.append(customConversion);
return true;
}
diff --git a/sources/shiboken6/cmake/ShibokenHelpers.cmake b/sources/shiboken6/cmake/ShibokenHelpers.cmake
index bcaf31e89..c6414b2ca 100644
--- a/sources/shiboken6/cmake/ShibokenHelpers.cmake
+++ b/sources/shiboken6/cmake/ShibokenHelpers.cmake
@@ -869,28 +869,9 @@ endfunction()
# Get path to libclang.dll/libclang.so depending on the platform
macro(find_libclang)
- if(CMAKE_HOST_WIN32)
- set(libclang_directory_suffix "bin")
- set(libclang_suffix ".dll")
- else()
- set(libclang_directory_suffix "lib")
- if(CMAKE_HOST_APPLE)
- set(libclang_suffix ".dylib")
- else()
- set(libclang_suffix ".so")
- endif()
- endif()
-
- set(libclang_lib_dir "")
- if(DEFINED ENV{LLVM_INSTALL_DIR})
- set(libclang_lib_dir "$ENV{LLVM_INSTALL_DIR}/${libclang_directory_suffix}")
- elseif(DEFINED ENV{CLANG_INSTALL_DIR})
- set(libclang_lib_dir "$ENV{CLANG_INSTALL_DIR}/${libclang_directory_suffix}")
- else()
- message(WARNING
- "Couldn't find libclang${libclang_suffix} "
- "You will likely need to add it manually to PATH to ensure the build succeeds.")
- endif()
+ find_package(Clang CONFIG REQUIRED)
+ get_target_property(libclang_location libclang LOCATION)
+ get_filename_component(libclang_lib_dir "${libclang_location}" DIRECTORY)
endmacro()
# Allow setting a shiboken debug level from the the build system or from the environment
diff --git a/sources/shiboken6/doc/typesystem_conversionrule.rst b/sources/shiboken6/doc/typesystem_conversionrule.rst
index cee45bfb3..f6ce18345 100644
--- a/sources/shiboken6/doc/typesystem_conversionrule.rst
+++ b/sources/shiboken6/doc/typesystem_conversionrule.rst
@@ -12,9 +12,13 @@ The **conversion-rule** tag specifies how a **primitive-type**, a **container-ty
or a **value-type** may be converted to and from the native C++ language types to the
target language types (see also :ref:`user-defined-type-conversion`).
-It is a child of the :ref:`container-type`, :ref:`primitive-type` or
-:ref:`value-type` and may contain :ref:`native-to-target` or
-:ref:`native-to-target` child nodes.
+It may be a child of the :ref:`container-type` and :ref:`primitive-type` nodes,
+where conversions have to be provided for both directions using the
+:ref:`native-to-target` and :ref:`target-to-native` child nodes.
+
+It may also appear as a child of :ref:`value-type` or :ref:`smart-pointer-type`
+where additional conversions from other target language types can be provided
+using the :ref:`target-to-native` child node.
.. code-block:: xml
@@ -70,8 +74,9 @@ an input value an does what's needed to convert it to the output value.
</conversion-rule>
Use the replace node to modify the template code.
-Notice that the generator must provide type system variables for the input
-and output values and types, namely **%in**, **%out**, **%INTYPE** and
+Notice that the generator provides type system variables for the input
+and output values and types (see :ref:`converter_variables_and_functions`).
+The most important ones are **%in**, **%out**, **%INTYPE** and
**%OUTTYPE**. In the case of container types, **%INTYPE** refers to the
full container type (e.g. **"list<int>"**) and **%INTYPE_0**, **%INTYPE_1**,
**%INTYPE_#**, should be replaced by the types used in the container template
diff --git a/sources/shiboken6/doc/typesystem_converters.rst b/sources/shiboken6/doc/typesystem_converters.rst
index ab6fba930..f34f5b829 100644
--- a/sources/shiboken6/doc/typesystem_converters.rst
+++ b/sources/shiboken6/doc/typesystem_converters.rst
@@ -16,7 +16,8 @@ C++ and vice-versa.
// C++ class
struct Complex {
- Complex(double real, double imag);
+ explicit Complex(double real, double imag);
+
double real() const;
double imag() const;
};
@@ -82,8 +83,9 @@ Here's how to do it:
<!-- Code injection at module level. -->
<inject-code class="native" position="beginning">
- static bool Check2TupleOfNumbers(PyObject* pyIn) {
- if (!PySequence_Check(pyIn) || !(PySequence_Size(pyIn) == 2))
+ static bool Check2TupleOfNumbers(PyObject *pyIn)
+ {
+ if (PySequence_Check(pyIn) == 0 || PySequence_Size(pyIn) != 2)
return false;
Shiboken::AutoDecRef pyReal(PySequence_GetItem(pyIn, 0));
if (!PyNumber_Check(pyReal))
@@ -134,7 +136,8 @@ Container Conversions
Converters for :ref:`container-type <container-type>` are pretty much the same as for other type,
except that they make use of the type system variables
-:ref:`%INTYPE_# <intype_n>` and :ref:`%OUTTYPE_# <outtype_n>`.
+:ref:`%INTYPE_# <intype_n>` and :ref:`%OUTTYPE_# <outtype_n>` denoting the
+template parameters.
|project| combines the conversion code for containers with the conversion
defined (or automatically generated) for the containers.
@@ -147,13 +150,12 @@ defined (or automatically generated) for the containers.
<native-to-target>
PyObject* %out = PyDict_New();
- %INTYPE::const_iterator it = %in.begin();
- for (; it != %in.end(); ++it) {
- %INTYPE_0 key = it->first;
- %INTYPE_1 value = it->second;
- PyDict_SetItem(%out,
+ for (auto it = %in.cbegin(), end = %in.cend(); it != end; ++it) {
+ const auto &amp;key = it->first;
+ const auto &amp;value = it->second;
+ PyDict_SetItem(%out,
%CONVERTTOPYTHON[%INTYPE_0](key),
- %CONVERTTOPYTHON[%INTYPE_1](value));
+ %CONVERTTOPYTHON[%INTYPE_1](value));
}
return %out;
</native-to-target>
@@ -161,8 +163,8 @@ defined (or automatically generated) for the containers.
<target-to-native>
<add-conversion type="PyDict">
- PyObject* key;
- PyObject* value;
+ PyObject *key{};
+ PyObject *value{};
Py_ssize_t pos = 0;
while (PyDict_Next(%in, &amp;pos, &amp;key, &amp;value)) {
%OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key);
@@ -183,10 +185,10 @@ defined (or automatically generated) for the containers.
For this case, a number of pre-defined conversion templates
are provided (see :ref:`predefined_templates`).
-.. _variables_and_functions:
+.. _converter_variables_and_functions:
-Variables & Functions
-=====================
+Converter Variables & Functions
+===============================
.. _in:
@@ -212,7 +214,7 @@ Variables & Functions
.. _intype_n:
**%INTYPE_#**
- Replaced by the name of the #th type used in a container.
+ Replaced by the name of the #th template parameter type used in a container.
.. _outtype:
@@ -225,7 +227,7 @@ Variables & Functions
.. _outtype_n:
**%OUTTYPE_#**
- Replaced by the name of the #th type used in a container.
+ Replaced by the name of the #th template parameter type used in a container.
.. _checktype:
diff --git a/sources/shiboken6/doc/typesystem_specifying_types.rst b/sources/shiboken6/doc/typesystem_specifying_types.rst
index c03d203b9..798ef5719 100644
--- a/sources/shiboken6/doc/typesystem_specifying_types.rst
+++ b/sources/shiboken6/doc/typesystem_specifying_types.rst
@@ -208,6 +208,9 @@ can be generated for them. Instead, an instance of the viewed class should
be instantiated and passed to functions using the view class
for argument types.
+It is also possible to specify template specializations
+like "std::optional<int>" as primitive types with converters.
+
See :ref:`predefined_templates` for built-in templates for standard type
conversion rules.
@@ -726,7 +729,8 @@ The ``smart pointer`` type node indicates that the given class is a smart pointe
and requires inserting calls to **getter** to access the pointeee.
Currently, the usage is limited to function return values.
**ref-count-method** specifies the name of the method used to do reference counting.
-It is a child of the :ref:`typesystem_details` node or other type nodes.
+It is a child of the :ref:`typesystem_details` node or other type nodes
+and may contain :ref:`conversion-rule` nodes.
The *optional* attribute **instantiations** specifies for which instantiations
of the smart pointer wrappers will be generated (comma-separated list).
diff --git a/sources/shiboken6/doc/typesystem_variables.rst b/sources/shiboken6/doc/typesystem_variables.rst
index 5eb5d5abe..6dfd1f801 100644
--- a/sources/shiboken6/doc/typesystem_variables.rst
+++ b/sources/shiboken6/doc/typesystem_variables.rst
@@ -16,6 +16,8 @@ implementation specifics.
Variables
=========
+In addition to the below listed variables, there are some variables specific to type
+conversion code (see :ref:`converter_variables_and_functions`).
.. _cpp_return_argument:
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
index 21e167b53..9092768a3 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
@@ -997,7 +997,7 @@ void CppGenerator::writeCacheResetNative(TextStream &s, const GeneratorContext &
{
s << "void " << classContext.wrapperName()
<< "::resetPyMethodCache()\n{\n" << indent
- << "std::fill_n(m_PyMethodCache, sizeof(m_PyMethodCache) / sizeof(m_PyMethodCache[0]), false);\n"
+ << "std::fill(m_PyMethodCache.begin(), m_PyMethodCache.end(), nullptr);\n"
<< outdent << "}\n\n";
}
@@ -2120,6 +2120,24 @@ void CppGenerator::writeCustomConverterRegister(TextStream &s,
}
}
+void CppGenerator::writeTemplateCustomConverterRegister(TextStream &s,
+ const AbstractMetaType &type,
+ QString converter)
+{
+ auto customConversion = CustomConversion::getCustomConversion(type.typeEntry());
+ if (!customConversion || customConversion->targetToNativeConversions().isEmpty())
+ return;
+ if (converter.isEmpty())
+ converter = converterVar;
+ const QString typeName = fixedCppTypeName(type);
+ for (const auto &conv : customConversion->targetToNativeConversions()) {
+ const QString &sourceTypeName = conv.sourceTypeName();
+ QString toCpp = pythonToCppFunctionName(sourceTypeName, typeName);
+ QString isConv = convertibleToCppFunctionName(sourceTypeName, typeName);
+ writeAddPythonToCppConversion(s, converter, toCpp, isConv);
+ }
+}
+
void CppGenerator::writeContainerConverterFunctions(TextStream &s,
const AbstractMetaType &containerType) const
{
@@ -3600,13 +3618,15 @@ void CppGenerator::writePythonToCppConversionFunctions(TextStream &s,
writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, typeCheck);
}
-void CppGenerator::writePythonToCppConversionFunctions(TextStream &s, const AbstractMetaType &containerType) const
+void CppGenerator::writePythonToCppConversionFunctions(TextStream &s,
+ const AbstractMetaType &templateType) const
{
- Q_ASSERT(containerType.typeEntry()->isContainer());
- const auto cte = std::static_pointer_cast<const ContainerTypeEntry>(containerType.typeEntry());
- const auto customConversion = cte->customConversion();
- for (const auto &conv : customConversion->targetToNativeConversions())
- writePythonToCppConversionFunction(s, containerType, conv);
+ const auto customConversion = CustomConversion::getCustomConversion(templateType.typeEntry());
+ if (customConversion) {
+ const auto &conversions = customConversion->targetToNativeConversions();
+ for (const auto &conv : conversions)
+ writePythonToCppConversionFunction(s, templateType, conv);
+ }
}
void CppGenerator::writePythonToCppConversionFunction(TextStream &s,
@@ -4438,8 +4458,7 @@ QString CppGenerator::writeContainerConverterInitialization(TextStream &s,
s << '&' << targetTypeName << "_Type";
}
- const QString typeName = fixedCppTypeName(type);
- s << ", " << cppToPythonFunctionName(typeName, targetTypeName) << ");\n";
+ s << ", " << cppToPythonFunctionName(fixedCppTypeName(type), targetTypeName) << ");\n";
s << registerConverterName(cppSignature, converter);
if (usePySideExtensions() && cppSignature.startsWith("const "_L1)
@@ -4448,12 +4467,7 @@ QString CppGenerator::writeContainerConverterInitialization(TextStream &s,
s << registerConverterName(underlyingType, converter);
}
- for (const auto &conv : typeEntry->customConversion()->targetToNativeConversions()) {
- const QString &sourceTypeName = conv.sourceTypeName();
- QString toCpp = pythonToCppFunctionName(sourceTypeName, typeName);
- QString isConv = convertibleToCppFunctionName(sourceTypeName, typeName);
- writeAddPythonToCppConversion(s, converter, toCpp, isConv);
- }
+ writeTemplateCustomConverterRegister(s, type, converter);
auto typedefItPair = api.typedefTargetToName().equal_range(type.cppSignature());
if (typedefItPair.first != typedefItPair.second) {
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h
index 0cf204234..441a9f781 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.h
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.h
@@ -114,6 +114,9 @@ private:
static void writeCustomConverterRegister(TextStream &s,
const CustomConversionPtr &customConversion,
const QString &converterVar);
+ static void writeTemplateCustomConverterRegister(TextStream &s,
+ const AbstractMetaType &type,
+ QString converter = {});
void writeContainerConverterFunctions(TextStream &s,
const AbstractMetaType &containerType) const;
@@ -361,9 +364,10 @@ private:
const TargetToNativeConversion &toNative,
const TypeEntryCPtr &targetType) const;
- /// Writes a pair of Python to C++ conversion and check functions for instantiated container types.
+ /// Writes a pair of Python to C++ conversion and check functions for instantiated
+ /// template (smart pointer/container types).
void writePythonToCppConversionFunctions(TextStream &s,
- const AbstractMetaType &containerType) const;
+ const AbstractMetaType &templateType) const;
void writePythonToCppConversionFunction(TextStream &s,
const AbstractMetaType &containerType,
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp b/sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp
index 48c4ed5d2..1d3280e36 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp
@@ -232,13 +232,16 @@ void CppGenerator::generateSmartPointerClass(TextStream &s,
void CppGenerator::writeSmartPointerConverterFunctions(TextStream &s,
const AbstractMetaType &smartPointerType) const
{
+ auto smartPointerTypeEntry =
+ std::static_pointer_cast<const SmartPointerTypeEntry>(smartPointerType.typeEntry());
+
+ if (smartPointerTypeEntry->hasCustomConversion())
+ writePythonToCppConversionFunctions(s, smartPointerType);
+
const auto baseClasses = findSmartPointeeBaseClasses(api(), smartPointerType);
if (baseClasses.isEmpty())
return;
- auto smartPointerTypeEntry =
- std::static_pointer_cast<const SmartPointerTypeEntry>(smartPointerType.typeEntry());
-
// TODO: Missing conversion to smart pointer pointer type:
s << "// Register smartpointer conversion for all derived classes\n";
@@ -290,6 +293,8 @@ void CppGenerator::writeSmartPointerConverterInitialization(TextStream &s,
writeAddPythonToCppConversion(s, targetConverter, toCpp, isConv);
};
+ writeTemplateCustomConverterRegister(s, type);
+
const auto classes = findSmartPointeeBaseClasses(api(), type);
if (classes.isEmpty())
return;
diff --git a/sources/shiboken6/generator/shiboken/headergenerator.cpp b/sources/shiboken6/generator/shiboken/headergenerator.cpp
index 965d80dad..7616fa5c3 100644
--- a/sources/shiboken6/generator/shiboken/headergenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/headergenerator.cpp
@@ -185,6 +185,7 @@ void HeaderGenerator::writeWrapperClass(TextStream &s,
for( const auto &includeGroup : includeGroups)
s << includeGroup;
}
+ s << "#include <sbkpython.h>\n\n#include <array>\n";
s << "namespace Shiboken { class AutoDecRef; class GilState; }\n\n";
@@ -288,9 +289,10 @@ void *qt_metacast(const char *_clname) override;
}
if (needsMethodCache) {
- s << "mutable bool m_PyMethodCache[" << maxOverrides << "] = {false";
+ s << "mutable std::array<PyObject *, " << maxOverrides
+ << "> m_PyMethodCache = {nullptr";
for (int i = 1; i < maxOverrides; ++i)
- s << ", false";
+ s << ", nullptr";
s << "};\n";
}
diff --git a/sources/shiboken6/libshiboken/basewrapper.cpp b/sources/shiboken6/libshiboken/basewrapper.cpp
index 3e26b4605..039cd3085 100644
--- a/sources/shiboken6/libshiboken/basewrapper.cpp
+++ b/sources/shiboken6/libshiboken/basewrapper.cpp
@@ -21,6 +21,7 @@
#include "voidptr.h"
#include <algorithm>
+#include <cctype>
#include <cstddef>
#include <cstring>
#include <iostream>
@@ -786,32 +787,57 @@ static PyObject *overrideMethodName(PyObject *pySelf, const char *methodName,
// The virtual function call
PyObject *Sbk_GetPyOverride(const void *voidThis, PyTypeObject *typeObject,
Shiboken::GilState &gil, const char *funcName,
- bool &resultCache, PyObject **nameCache)
-{
- PyObject *pyOverride{};
- if (!resultCache) {
- gil.acquire();
- auto &bindingManager = Shiboken::BindingManager::instance();
- SbkObject *wrapper = bindingManager.retrieveWrapper(voidThis, typeObject);
- // The refcount can be 0 if the object is dieing and someone called
- // a virtual method from the destructor
- if (wrapper == nullptr)
- return nullptr;
- auto *pySelf = reinterpret_cast<PyObject *>(wrapper);
- if (Py_REFCNT(pySelf) == 0)
- return nullptr;
- PyObject *pyMethodName = overrideMethodName(pySelf, funcName, nameCache);
- pyOverride = Shiboken::BindingManager::getOverride(wrapper, pyMethodName);
- if (pyOverride == nullptr) {
- resultCache = true;
- gil.release();
- } else if (Shiboken::Errors::occurred() != nullptr) {
- // Give up.
- Py_XDECREF(pyOverride);
- pyOverride = nullptr;
- }
+ PyObject *&resultCache, PyObject **nameCache)
+{
+ if (Py_IsInitialized() == 0 || resultCache == Py_None)
+ return nullptr; // Bail out, execute C++ call (wrappers may outlive Python).
+
+ auto &bindingManager = Shiboken::BindingManager::instance();
+ SbkObject *wrapper = bindingManager.retrieveWrapper(voidThis, typeObject);
+ // The refcount can be 0 if the object is dieing and someone called
+ // a virtual method from the destructor
+ if (wrapper == nullptr)
+ return nullptr;
+ auto *pySelf = reinterpret_cast<PyObject *>(wrapper);
+ if (Py_REFCNT(pySelf) == 0)
+ return nullptr;
+
+ gil.acquire();
+
+ if (resultCache != nullptr) // recreate the callable from function/self
+ return PepExt_Type_CallDescrGet(resultCache, pySelf, nullptr);
+
+ PyObject *pyMethodName = overrideMethodName(pySelf, funcName, nameCache);
+ auto *wrapper_dict = SbkObject_GetDict_NoRef(pySelf);
+
+ // Note: This special case was implemented for duck-punching, which happens
+ // in the instance dict. It does not work with properties.
+ // This is not cached to avoid leaking. FIXME PYSIDE 7: Remove (PYSIDE-2916)?
+ if (PyObject *method = PyDict_GetItem(wrapper_dict, pyMethodName)) {
+ Py_INCREF(method);
+ return method;
+ }
+
+ auto *pyOverride = Shiboken::BindingManager::getOverride(wrapper, pyMethodName);
+ if (pyOverride == nullptr) {
+ resultCache = Py_None;
+ Py_INCREF(resultCache);
+ gil.release();
+ return nullptr; // No override, execute C++ call
}
- return pyOverride;
+
+ if (Shiboken::Errors::occurred() != nullptr) {
+ // Give up.
+ Py_XDECREF(pyOverride);
+ resultCache = Py_None;
+ Py_INCREF(resultCache);
+ gil.release();
+ return nullptr; // // Give up.
+ }
+
+ resultCache = pyOverride;
+ // recreate the callable from function/self
+ return PepExt_Type_CallDescrGet(resultCache, pySelf, nullptr);
}
namespace
diff --git a/sources/shiboken6/libshiboken/basewrapper.h b/sources/shiboken6/libshiboken/basewrapper.h
index 9eea89540..426298bcf 100644
--- a/sources/shiboken6/libshiboken/basewrapper.h
+++ b/sources/shiboken6/libshiboken/basewrapper.h
@@ -123,9 +123,8 @@ LIBSHIBOKEN_API PyObject *Sbk_ReturnFromPython_Self(PyObject *self);
} // extern "C"
LIBSHIBOKEN_API PyObject *Sbk_GetPyOverride(const void *voidThis, PyTypeObject *typeObject,
- Shiboken::GilState &gil,
- const char *funcName, bool &resultCache,
- PyObject **nameCache);
+ Shiboken::GilState &gil, const char *funcName,
+ PyObject *&resultCache, PyObject **nameCache);
namespace Shiboken
{
diff --git a/sources/shiboken6/libshiboken/bindingmanager.cpp b/sources/shiboken6/libshiboken/bindingmanager.cpp
index 25cc5c00a..ca509aefd 100644
--- a/sources/shiboken6/libshiboken/bindingmanager.cpp
+++ b/sources/shiboken6/libshiboken/bindingmanager.cpp
@@ -369,13 +369,6 @@ SbkObject *BindingManager::retrieveWrapper(const void *cptr, PyTypeObject *typeO
PyObject *BindingManager::getOverride(SbkObject *wrapper, PyObject *pyMethodName)
{
auto *obWrapper = reinterpret_cast<PyObject *>(wrapper);
- auto *wrapper_dict = SbkObject_GetDict_NoRef(obWrapper);
- if (PyObject *method = PyDict_GetItem(wrapper_dict, pyMethodName)) {
- // Note: This special case was implemented for duck-punching, which happens
- // in the instance dict. It does not work with properties.
- Py_INCREF(method);
- return method;
- }
Shiboken::AutoDecRef method(PyObject_GetAttr(obWrapper, pyMethodName));
if (method.isNull())
@@ -387,9 +380,9 @@ PyObject *BindingManager::getOverride(SbkObject *wrapper, PyObject *pyMethodName
// crude check for them.
// PYSIDE-535: This macro is redefined in a compatible way in pep384
if (PyMethod_Check(method) != 0) {
- if (PyMethod_GET_SELF(method) != obWrapper)
+ if (PyMethod_Self(method) != obWrapper)
return nullptr;
- function = PyMethod_GET_FUNCTION(method);
+ function = PyMethod_Function(method);
} else if (isCompiledMethod(method)) {
Shiboken::AutoDecRef im_self(PyObject_GetAttr(method, PyName::im_self()));
// Not retaining a reference inline with what PyMethod_GET_SELF does.
@@ -413,13 +406,13 @@ PyObject *BindingManager::getOverride(SbkObject *wrapper, PyObject *pyMethodName
if (PyObject *defaultMethod = PyDict_GetItem(parentDict.object(), pyMethodName)) {
defaultFound = true;
if (function != defaultMethod)
- return method.release();
+ return function;
}
}
}
// PYSIDE-2255: If no default method was found, use the method.
if (!defaultFound)
- return method.release();
+ return function;
return nullptr;
}
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py
index 109562a98..8eea431c3 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py
@@ -352,6 +352,7 @@ def create_signature_union(props, key):
if last == _VAR_POSITIONAL:
kind = _KEYWORD_ONLY
if default is None:
+ ann = typing.Union[ann]
ann = typing.Optional[ann]
if default is not _empty and layout.ellipsis:
default = ellipsis
@@ -373,6 +374,7 @@ def create_signature_union(props, key):
ret_anno = annotations.get('return', _empty)
if ret_anno is not _empty and props["fullname"] in missing_optional_return:
+ ret_anno = typing.Union[ret_anno]
ret_anno = typing.Optional[ret_anno]
return inspect.Signature(params, return_annotation=ret_anno,
__validate_parameters__=False)
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py
index c5dc44644..1031e0bb0 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py
@@ -69,12 +69,12 @@ class Formatter(Writer):
backup = inspect.formatannotation
@classmethod
- def formatannotation(cls, annotation, base_module=None):
+ def formatannotation(cls, annotation, base_module=None, *args, **kwargs):
if getattr(annotation, '__module__', None) == 'typing':
# do not remove the prefix!
return repr(annotation)
# do the normal action.
- return cls.backup(annotation, base_module)
+ return cls.backup(annotation, base_module, *args, **kwargs)
@classmethod
def fix_typing_prefix(cls, signature):
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
index 2bb3c9a87..84cb15feb 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
@@ -509,6 +509,7 @@ def init_PySide6_QtCore():
"PySide6.QtCore.QUrl.ComponentFormattingOptions":
PySide6.QtCore.QUrl.ComponentFormattingOption, # mismatch option/enum, why???
"PyUnicode": typing.Text,
+ "QByteArray": typing.Union[PySide6.QtCore.QByteArray, bytes, bytearray, memoryview],
"QByteArrayView": PySide6.QtCore.QByteArray,
"Q_NULLPTR": None,
"QCalendar.Unspecified": PySide6.QtCore.QCalendar.Unspecified,
diff --git a/sources/shiboken6/tests/libsample/bucket.cpp b/sources/shiboken6/tests/libsample/bucket.cpp
index cafd382a9..43a32f414 100644
--- a/sources/shiboken6/tests/libsample/bucket.cpp
+++ b/sources/shiboken6/tests/libsample/bucket.cpp
@@ -40,15 +40,21 @@ bool Bucket::empty()
void Bucket::lock()
{
- m_locked = true;
- while (m_locked) {
- SLEEP(300);
+ bool expected = false;
+ if (m_locked.compare_exchange_strong(expected, true)) {
+ while (m_locked) {
+ SLEEP(300);
+ }
+ } else {
+ std::cerr << __FUNCTION__ << " Attempt to lock twice.\n";
}
}
void Bucket::unlock()
{
- m_locked = false;
+ bool expected = true;
+ if (!m_locked.compare_exchange_strong(expected, false))
+ std::cerr << __FUNCTION__ << " Attempt to unlock twice.\n";
}
bool Bucket::virtualBlockerMethod()
diff --git a/sources/shiboken6/tests/libsample/bucket.h b/sources/shiboken6/tests/libsample/bucket.h
index 73e8edd78..677069fe7 100644
--- a/sources/shiboken6/tests/libsample/bucket.h
+++ b/sources/shiboken6/tests/libsample/bucket.h
@@ -7,6 +7,7 @@
#include "libsamplemacros.h"
#include "objecttype.h"
+#include <atomic>
#include <list>
class ObjectType;
@@ -19,7 +20,7 @@ public:
int pop();
bool empty();
void lock();
- inline bool locked() { return m_locked; }
+ bool locked() { return m_locked.load(); }
void unlock();
virtual bool virtualBlockerMethod();
@@ -27,8 +28,7 @@ public:
private:
std::list<int> m_data;
-
- volatile bool m_locked = false;
+ std::atomic<bool> m_locked{false};
};
#endif // BUCKET_H
diff --git a/sources/shiboken6/tests/libsample/samplenamespace.cpp b/sources/shiboken6/tests/libsample/samplenamespace.cpp
index 18a18d28d..3836f43aa 100644
--- a/sources/shiboken6/tests/libsample/samplenamespace.cpp
+++ b/sources/shiboken6/tests/libsample/samplenamespace.cpp
@@ -97,6 +97,15 @@ int passReferenceToObjectType(const ObjectType &obj, int multiplier)
return obj.objectName().size() * multiplier;
}
+// Exercise specifying complete template specializations as primitive types.
+std::optional<long> optionalMultiply(const std::optional<long> &v1,
+ const std::optional<long> &v2)
+{
+ if (!v1.has_value() || !v2.has_value())
+ return std::nullopt;
+ return v1.value() * v2.value();
+}
+
int variableInNamespace = 42;
} // namespace SampleNamespace
diff --git a/sources/shiboken6/tests/libsample/samplenamespace.h b/sources/shiboken6/tests/libsample/samplenamespace.h
index 99a0787ee..63dc2f316 100644
--- a/sources/shiboken6/tests/libsample/samplenamespace.h
+++ b/sources/shiboken6/tests/libsample/samplenamespace.h
@@ -9,6 +9,7 @@
#include "point.h"
#include "objecttype.h"
+#include <optional>
#include <list>
// Anonymous global enum
@@ -157,6 +158,9 @@ LIBSAMPLE_API double passReferenceToValueType(const Point &point, double multipl
// Add a new signature on type system with only a ObjectType pointer as parameter.
LIBSAMPLE_API int passReferenceToObjectType(const ObjectType &obj, int multiplier);
+LIBSAMPLE_API std::optional<long> optionalMultiply(const std::optional<long> &v1,
+ const std::optional<long> &v2);
+
extern LIBSAMPLE_API int variableInNamespace;
} // namespace SampleNamespace
diff --git a/sources/shiboken6/tests/samplebinding/sample_test.py b/sources/shiboken6/tests/samplebinding/sample_test.py
index c003ad398..43b84d36e 100644
--- a/sources/shiboken6/tests/samplebinding/sample_test.py
+++ b/sources/shiboken6/tests/samplebinding/sample_test.py
@@ -79,6 +79,13 @@ class ModuleTest(unittest.TestCase):
mo2 = sample.MoveOnlyHandler.passMoveOnly(mo)
self.assertEqual(mo2.value(), v)
+ def testOptionalLong(self):
+ v1 = 2
+ v2 = 3
+ self.assertEqual(sample.SampleNamespace.optionalMultiply(v1, v2), 6)
+ self.assertIsNone(sample.SampleNamespace.optionalMultiply(v1, None))
+ self.assertIsNone(sample.SampleNamespace.optionalMultiply(None, v2))
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
index 3f1b2e96f..391a0804d 100644
--- a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
+++ b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
@@ -120,6 +120,25 @@
</conversion-rule>
</primitive-type>
+ <primitive-type name="std::optional&lt;long&gt;" target-langapi-name="PyObject">
+ <conversion-rule>
+ <native-to-target>
+ if (!%in.has_value())
+ Py_RETURN_NONE;
+ return PyLong_FromLong(%in.value());
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type="Py_None">
+ SBK_UNUSED(%in)
+ %out = %OUTTYPE();
+ </add-conversion>
+ <add-conversion type="PyLong" check="PyLong_CheckExact(%in)">
+ %out = %OUTTYPE(PyLong_AsLong(%in));
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </primitive-type>
+
<value-type name="MoveOnly"/>
<object-type name="MoveOnlyHandler"/>