Skip to content

Commit e5c6221

Browse files
shiboken6: Add target-to-native conversion rules for smart pointers
Make it possible to construct for example a std::optional<int> directly from a PyLong, which helps avoiding exposing std::optional<int> as a type. Task-number: PYSIDE-3107 Change-Id: I0e600fa04119ea944ef256da1f06df5f86cc9a50 Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
1 parent 924ec80 commit e5c6221

File tree

9 files changed

+64
-19
lines changed

9 files changed

+64
-19
lines changed

sources/shiboken6/ApiExtractor/customconversion.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "containertypeentry.h"
66
#include "customtypenentry.h"
77
#include "primitivetypeentry.h"
8+
#include "smartpointertypeentry.h"
89
#include "valuetypeentry.h"
910

1011
#include <QtCore/qdebug.h>
@@ -139,6 +140,8 @@ CustomConversionPtr CustomConversion::getCustomConversion(const TypeEntryCPtr &t
139140
return std::static_pointer_cast<const ContainerTypeEntry>(type)->customConversion();
140141
if (type->isValue())
141142
return std::static_pointer_cast<const ValueTypeEntry>(type)->customConversion();
143+
if (type->isSmartPointer())
144+
return std::static_pointer_cast<const SmartPointerTypeEntry>(type)->customConversion();
142145
return {};
143146
}
144147

sources/shiboken6/ApiExtractor/smartpointertypeentry.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#define SMARTPOINTERTYPEENTRY_H
66

77
#include "complextypeentry.h"
8+
#include "customconversion_typedefs.h"
89

910
class SmartPointerTypeEntryPrivate;
1011

@@ -51,6 +52,10 @@ class SmartPointerTypeEntry : public ComplexTypeEntry
5152

5253
QString getTargetName(const AbstractMetaType &metaType) const;
5354

55+
bool hasCustomConversion() const;
56+
void setCustomConversion(const CustomConversionPtr &customConversion);
57+
CustomConversionPtr customConversion() const;
58+
5459
#ifndef QT_NO_DEBUG_STREAM
5560
void formatDebug(QDebug &d) const override;
5661
#endif

sources/shiboken6/ApiExtractor/typesystem.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2154,6 +2154,7 @@ class SmartPointerTypeEntryPrivate : public ComplexTypeEntryPrivate
21542154
QString m_resetMethod;
21552155
SmartPointerTypeEntry::Instantiations m_instantiations;
21562156
TypeEntryCList m_excludedInstantiations;
2157+
CustomConversionPtr m_customConversion;
21572158
TypeSystem::SmartPointerType m_smartPointerType;
21582159
};
21592160

@@ -2306,6 +2307,24 @@ QString SmartPointerTypeEntry::getTargetName(const AbstractMetaType &metaType) c
23062307
return fixSmartPointerName(name);
23072308
}
23082309

2310+
bool SmartPointerTypeEntry::hasCustomConversion() const
2311+
{
2312+
S_D(const SmartPointerTypeEntry);
2313+
return bool(d->m_customConversion);
2314+
}
2315+
2316+
void SmartPointerTypeEntry::setCustomConversion(const CustomConversionPtr &customConversion)
2317+
{
2318+
S_D(SmartPointerTypeEntry);
2319+
d->m_customConversion = customConversion;
2320+
}
2321+
2322+
CustomConversionPtr SmartPointerTypeEntry::customConversion() const
2323+
{
2324+
S_D(const SmartPointerTypeEntry);
2325+
return d->m_customConversion;
2326+
}
2327+
23092328
// ----------------- NamespaceTypeEntry
23102329
class NamespaceTypeEntryPrivate : public ComplexTypeEntryPrivate
23112330
{

sources/shiboken6/ApiExtractor/typesystemparser.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2348,9 +2348,10 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &,
23482348
if (topElement != StackElement::ModifyArgument
23492349
&& topElement != StackElement::ValueTypeEntry
23502350
&& topElement != StackElement::PrimitiveTypeEntry
2351-
&& topElement != StackElement::ContainerTypeEntry) {
2351+
&& topElement != StackElement::ContainerTypeEntry
2352+
&& topElement != StackElement::SmartPointerTypeEntry) {
23522353
m_error = u"Conversion rules can only be specified for argument modification, "
2353-
"value-type, primitive-type or container-type conversion."_s;
2354+
"value-type, primitive-type, or container-type or smartpointer-type conversion."_s;
23542355
return false;
23552356
}
23562357

@@ -2415,6 +2416,9 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &,
24152416
std::static_pointer_cast<ContainerTypeEntry>(top->entry)->setCustomConversion(customConversion);
24162417
else if (top->entry->isValue())
24172418
std::static_pointer_cast<ValueTypeEntry>(top->entry)->setCustomConversion(customConversion);
2419+
else if (top->entry->isSmartPointer())
2420+
std::static_pointer_cast<SmartPointerTypeEntry>(top->entry)->setCustomConversion(customConversion);
2421+
24182422
customConversionsForReview.append(customConversion);
24192423
return true;
24202424
}

sources/shiboken6/doc/typesystem_conversionrule.rst

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@ The **conversion-rule** tag specifies how a **primitive-type**, a **container-ty
1212
or a **value-type** may be converted to and from the native C++ language types to the
1313
target language types (see also :ref:`user-defined-type-conversion`).
1414

15-
It is a child of the :ref:`container-type`, :ref:`primitive-type` or
16-
:ref:`value-type` and may contain :ref:`native-to-target` or
17-
:ref:`native-to-target` child nodes.
15+
It may be a child of the :ref:`container-type` and :ref:`primitive-type` nodes,
16+
where conversions have to be provided for both directions using the
17+
:ref:`native-to-target` and :ref:`target-to-native` child nodes.
18+
19+
It may also appear as a child of :ref:`value-type` or :ref:`smart-pointer-type`
20+
where additional conversions from other target language types can be provided
21+
using the :ref:`target-to-native` child node.
1822

1923
.. code-block:: xml
2024
@@ -70,8 +74,9 @@ an input value an does what's needed to convert it to the output value.
7074
</conversion-rule>
7175
7276
Use the replace node to modify the template code.
73-
Notice that the generator must provide type system variables for the input
74-
and output values and types, namely **%in**, **%out**, **%INTYPE** and
77+
Notice that the generator provides type system variables for the input
78+
and output values and types (see :ref:`converter_variables_and_functions`).
79+
The most important ones are **%in**, **%out**, **%INTYPE** and
7580
**%OUTTYPE**. In the case of container types, **%INTYPE** refers to the
7681
full container type (e.g. **"list<int>"**) and **%INTYPE_0**, **%INTYPE_1**,
7782
**%INTYPE_#**, should be replaced by the types used in the container template

sources/shiboken6/doc/typesystem_specifying_types.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,8 @@ The ``smart pointer`` type node indicates that the given class is a smart pointe
729729
and requires inserting calls to **getter** to access the pointeee.
730730
Currently, the usage is limited to function return values.
731731
**ref-count-method** specifies the name of the method used to do reference counting.
732-
It is a child of the :ref:`typesystem_details` node or other type nodes.
732+
It is a child of the :ref:`typesystem_details` node or other type nodes
733+
and may contain :ref:`conversion-rule` nodes.
733734

734735
The *optional* attribute **instantiations** specifies for which instantiations
735736
of the smart pointer wrappers will be generated (comma-separated list).

sources/shiboken6/generator/shiboken/cppgenerator.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3618,13 +3618,15 @@ void CppGenerator::writePythonToCppConversionFunctions(TextStream &s,
36183618
writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, typeCheck);
36193619
}
36203620

3621-
void CppGenerator::writePythonToCppConversionFunctions(TextStream &s, const AbstractMetaType &containerType) const
3621+
void CppGenerator::writePythonToCppConversionFunctions(TextStream &s,
3622+
const AbstractMetaType &templateType) const
36223623
{
3623-
Q_ASSERT(containerType.typeEntry()->isContainer());
3624-
const auto cte = std::static_pointer_cast<const ContainerTypeEntry>(containerType.typeEntry());
3625-
const auto customConversion = cte->customConversion();
3626-
for (const auto &conv : customConversion->targetToNativeConversions())
3627-
writePythonToCppConversionFunction(s, containerType, conv);
3624+
const auto customConversion = CustomConversion::getCustomConversion(templateType.typeEntry());
3625+
if (customConversion) {
3626+
const auto &conversions = customConversion->targetToNativeConversions();
3627+
for (const auto &conv : conversions)
3628+
writePythonToCppConversionFunction(s, templateType, conv);
3629+
}
36283630
}
36293631

36303632
void CppGenerator::writePythonToCppConversionFunction(TextStream &s,

sources/shiboken6/generator/shiboken/cppgenerator.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,9 +364,10 @@ class CppGenerator : public ShibokenGenerator
364364
const TargetToNativeConversion &toNative,
365365
const TypeEntryCPtr &targetType) const;
366366

367-
/// Writes a pair of Python to C++ conversion and check functions for instantiated container types.
367+
/// Writes a pair of Python to C++ conversion and check functions for instantiated
368+
/// template (smart pointer/container types).
368369
void writePythonToCppConversionFunctions(TextStream &s,
369-
const AbstractMetaType &containerType) const;
370+
const AbstractMetaType &templateType) const;
370371

371372
void writePythonToCppConversionFunction(TextStream &s,
372373
const AbstractMetaType &containerType,

sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,13 +232,16 @@ void CppGenerator::generateSmartPointerClass(TextStream &s,
232232
void CppGenerator::writeSmartPointerConverterFunctions(TextStream &s,
233233
const AbstractMetaType &smartPointerType) const
234234
{
235+
auto smartPointerTypeEntry =
236+
std::static_pointer_cast<const SmartPointerTypeEntry>(smartPointerType.typeEntry());
237+
238+
if (smartPointerTypeEntry->hasCustomConversion())
239+
writePythonToCppConversionFunctions(s, smartPointerType);
240+
235241
const auto baseClasses = findSmartPointeeBaseClasses(api(), smartPointerType);
236242
if (baseClasses.isEmpty())
237243
return;
238244

239-
auto smartPointerTypeEntry =
240-
std::static_pointer_cast<const SmartPointerTypeEntry>(smartPointerType.typeEntry());
241-
242245
// TODO: Missing conversion to smart pointer pointer type:
243246

244247
s << "// Register smartpointer conversion for all derived classes\n";
@@ -290,6 +293,8 @@ void CppGenerator::writeSmartPointerConverterInitialization(TextStream &s,
290293
writeAddPythonToCppConversion(s, targetConverter, toCpp, isConv);
291294
};
292295

296+
writeTemplateCustomConverterRegister(s, type);
297+
293298
const auto classes = findSmartPointeeBaseClasses(api(), type);
294299
if (classes.isEmpty())
295300
return;

0 commit comments

Comments
 (0)