summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cppgenerator.cpp93
-rw-r--r--headergenerator.cpp43
-rw-r--r--shibokengenerator.cpp27
-rw-r--r--shibokengenerator.h2
-rw-r--r--tests/libsample/protected.h6
-rwxr-xr-xtests/samplebinding/protected_test.py36
-rw-r--r--tests/samplebinding/typesystem_sample.xml2
7 files changed, 177 insertions, 32 deletions
diff --git a/cppgenerator.cpp b/cppgenerator.cpp
index 2d30be2c..e2351094 100644
--- a/cppgenerator.cpp
+++ b/cppgenerator.cpp
@@ -477,15 +477,22 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu
Indentation indentation(INDENT);
ac << INDENT;
- if (convert && !hasConversionRule) {
+ if (convert && !hasConversionRule)
writeToPythonConversion(ac, arg->type(), func->ownerClass());
- ac << '(';
- }
- if (hasConversionRule)
+ if (hasConversionRule) {
ac << arg->argumentName() << "_out";
- else
- ac << arg->argumentName() << (convert ? ")" : "");
+ } else {
+ QString argName = arg->argumentName();
+#ifdef AVOID_PROTECTED_HACK
+ const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(arg->type());
+ if (metaEnum && metaEnum->isProtected()) {
+ argName.prepend(protectedEnumSurrogateName(metaEnum) + '(');
+ argName.append(')');
+ }
+#endif
+ ac << (convert ? "(" : "") << argName << (convert ? ")" : "");
+ }
argConversions << argConv;
}
@@ -530,10 +537,17 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu
if (func->typeReplaced(0).isEmpty()) {
s << cpythonCheckFunction(func->type());
// SbkType would return null when the type is a container.
- if (func->type()->typeEntry()->isContainer())
+ if (func->type()->typeEntry()->isContainer()) {
desiredType = '"' + reinterpret_cast<const ContainerTypeEntry*>(func->type()->typeEntry())->typeName() + '"';
- else
- desiredType = "SbkType<" + func->type()->cppSignature() + " >()->tp_name";
+ } else {
+ QString typeName = func->type()->cppSignature();
+#ifdef AVOID_PROTECTED_HACK
+ const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(func->type());
+ if (metaEnum && metaEnum->isProtected())
+ typeName = protectedEnumSurrogateName(metaEnum);
+#endif
+ desiredType = "SbkType<" + typeName + " >()->tp_name";
+ }
} else {
s << guessCPythonCheckFunction(func->typeReplaced(0));
desiredType = '"' + func->typeReplaced(0) + '"';
@@ -561,8 +575,28 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu
writeCodeSnips(s, convRule, CodeSnip::Any, TypeSystem::NativeCode, func);
} else if (!injectedCodeHasReturnValueAttribution(func, TypeSystem::NativeCode)) {
s << INDENT;
- s << translateTypeForWrapperMethod(func->type(), func->implementingClass()) << " " CPP_RETURN_VAR "(";
+#ifdef AVOID_PROTECTED_HACK
+ QString enumName;
+ const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(func->type());
+ bool isProtectedEnum = metaEnum && metaEnum->isProtected();
+ if (isProtectedEnum) {
+ enumName = metaEnum->name();
+ if (metaEnum->enclosingClass())
+ enumName = metaEnum->enclosingClass()->qualifiedCppName() + "::" + enumName;
+ s << enumName;
+ } else
+#endif
+ s << translateTypeForWrapperMethod(func->type(), func->implementingClass());
+ s << " " CPP_RETURN_VAR "(";
+#ifdef AVOID_PROTECTED_HACK
+ if (isProtectedEnum)
+ s << enumName << '(';
+#endif
writeToCppConversion(s, func->type(), func->implementingClass(), PYTHON_RETURN_VAR);
+#ifdef AVOID_PROTECTED_HACK
+ if (isProtectedEnum)
+ s << ')';
+#endif
s << ')';
s << ';' << endl;
}
@@ -1601,10 +1635,25 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f
if (func->allowThread())
s << INDENT << THREAD_STATE_SAVER_VAR ".save();" << endl;
s << INDENT;
- if (isCtor)
+ if (isCtor) {
s << "cptr = ";
- else if (func->type() && !func->isInplaceOperator())
- s << func->type()->cppSignature() << " " CPP_RETURN_VAR " = ";
+ } else if (func->type() && !func->isInplaceOperator()) {
+#ifdef AVOID_PROTECTED_HACK
+ QString enumName;
+ const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(func->type());
+ if (metaEnum) {
+ if (metaEnum->isProtected())
+ enumName = protectedEnumSurrogateName(metaEnum);
+ else
+ enumName = func->type()->cppSignature();
+ methodCall.prepend(enumName + '(');
+ methodCall.append(')');
+ s << enumName;
+ } else
+#endif
+ s << func->type()->cppSignature();
+ s << " " CPP_RETURN_VAR " = ";
+ }
s << methodCall << ';' << endl;
if (func->allowThread())
s << INDENT << THREAD_STATE_SAVER_VAR ".restore();" << endl;
@@ -2394,10 +2443,20 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu
s << cpythonName << "_Type," << endl;
{
Indentation indent(INDENT);
- s << INDENT << "(long) ";
- if (cppEnum->enclosingClass())
- s << cppEnum->enclosingClass()->qualifiedCppName() << "::";
- s << enumValue->name() << ", \"" << enumValue->name() << "\");" << endl;
+ s << INDENT;
+#ifdef AVOID_PROTECTED_HACK
+ if (!cppEnum->isProtected()) {
+#endif
+ s << "(long) ";
+ if (cppEnum->enclosingClass())
+ s << cppEnum->enclosingClass()->qualifiedCppName() << "::";
+ s << enumValue->name();
+#ifdef AVOID_PROTECTED_HACK
+ } else {
+ s << enumValue->value();
+ }
+#endif
+ s << ", \"" << enumValue->name() << "\");" << endl;
}
s << INDENT << addFunction << endl;
diff --git a/headergenerator.cpp b/headergenerator.cpp
index 3310227f..ca6b5daf 100644
--- a/headergenerator.cpp
+++ b/headergenerator.cpp
@@ -120,9 +120,22 @@ void HeaderGenerator::writeFunction(QTextStream& s, const AbstractMetaFunction*
#ifdef AVOID_PROTECTED_HACK
if (func->isProtected() && !func->isConstructor()) {
s << INDENT << "inline " << (func->isStatic() ? "static " : "");
- s << functionSignature(func, "", "_protected") << " { ";
+ s << functionSignature(func, "", "_protected", Generator::EnumAsInts|Generator::OriginalTypeDescription) << " { ";
s << (func->type() ? "return " : "") << func->ownerClass()->qualifiedCppName() << "::";
- writeFunctionCall(s, func);
+ s << func->originalName() << '(';
+ QStringList args;
+ foreach (const AbstractMetaArgument* arg, func->arguments()) {
+ QString argName = arg->argumentName();
+ const TypeEntry* enumTypeEntry = 0;
+ if (arg->type()->isFlags())
+ enumTypeEntry = reinterpret_cast<const FlagsTypeEntry*>(arg->type()->typeEntry())->originator();
+ else if (arg->type()->isEnum())
+ enumTypeEntry = arg->type()->typeEntry();
+ if (enumTypeEntry)
+ argName = QString("%1(%2)").arg(arg->type()->cppSignature()).arg(argName);
+ args << argName;
+ }
+ s << args.join(", ") << ')';
s << "; }" << endl;
}
#endif
@@ -169,6 +182,15 @@ void HeaderGenerator::writeTypeConverterDecl(QTextStream& s, const TypeEntry* ty
bool isValueTypeWithImplConversions = type->isValue() && !implicitConvs.isEmpty();
bool hasCustomConversion = type->hasConversionRule();
QString typeT = type->name() + (isAbstractOrObjectType ? "*" : "");
+ QString typeName = type->name();
+
+#ifdef AVOID_PROTECTED_HACK
+ const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(type);
+ if (metaEnum && metaEnum->isProtected()) {
+ typeT = protectedEnumSurrogateName(metaEnum);
+ typeName = typeT;
+ }
+#endif
s << "struct Converter<" << typeT << " >";
if (!hasCustomConversion) {
@@ -178,7 +200,7 @@ void HeaderGenerator::writeTypeConverterDecl(QTextStream& s, const TypeEntry* ty
s << " : ObjectTypeConverter";
else
s << " : ValueTypeConverter";
- s << '<' << type->name() << " >";
+ s << '<' << typeName << " >";
}
s << endl << '{' << endl;
if (isValueTypeWithImplConversions || hasCustomConversion) {
@@ -398,11 +420,18 @@ void HeaderGenerator::writeExportMacros(QTextStream& s)
void HeaderGenerator::writeSbkTypeFunction(QTextStream& s, const AbstractMetaEnum* cppEnum)
{
- QString enumPrefix;
+ QString enumName = cppEnum->name();
if (cppEnum->enclosingClass())
- enumPrefix = cppEnum->enclosingClass()->qualifiedCppName() + "::";
- s << "template<> inline PyTypeObject* SbkType<" << enumPrefix << cppEnum->name() << " >() "
- << "{ return " << cpythonTypeNameExt(cppEnum->typeEntry()) << "; }\n";
+ enumName = cppEnum->enclosingClass()->qualifiedCppName() + "::" + enumName;
+#ifdef AVOID_PROTECTED_HACK
+ if (cppEnum->isProtected()) {
+ enumName = protectedEnumSurrogateName(cppEnum);
+ s << "enum " << enumName << " {};" << endl;
+ }
+#endif
+
+ s << "template<> inline PyTypeObject* SbkType<" << enumName << " >() ";
+ s << "{ return " << cpythonTypeNameExt(cppEnum->typeEntry()) << "; }\n";
FlagsTypeEntry* flag = cppEnum->typeEntry()->flags();
if (flag) {
diff --git a/shibokengenerator.cpp b/shibokengenerator.cpp
index 64976d3d..5b85ef43 100644
--- a/shibokengenerator.cpp
+++ b/shibokengenerator.cpp
@@ -157,10 +157,19 @@ QString ShibokenGenerator::translateTypeForWrapperMethod(const AbstractMetaType*
{
QString result;
- if (cType->isArray())
+ if (cType->isArray()) {
result = translateTypeForWrapperMethod(cType->arrayElementType(), context) + "[]";
- else
- result = translateType(cType, context);
+ } else {
+#ifdef AVOID_PROTECTED_HACK
+ if (cType->isEnum()) {
+ const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(cType);
+ if (metaEnum && metaEnum->isProtected())
+ result = protectedEnumSurrogateName(metaEnum);
+ }
+ if (result.isEmpty())
+#endif
+ result = translateType(cType, context);
+ }
return result;
}
@@ -188,6 +197,11 @@ QString ShibokenGenerator::wrapperName(const AbstractMetaClass* metaClass)
}
}
+QString ShibokenGenerator::protectedEnumSurrogateName(const AbstractMetaEnum* metaEnum)
+{
+ return metaEnum->fullName().replace(".", "_") + "_Surrogate";
+}
+
QString ShibokenGenerator::cpythonFunctionName(const AbstractMetaFunction* func)
{
QString result;
@@ -299,6 +313,13 @@ void ShibokenGenerator::writeBaseConversion(QTextStream& s, const TypeEntry* typ
QString typeName = type->name();
if (type->isObject())
typeName.append('*');
+#ifdef AVOID_PROTECTED_HACK
+ if (type->isEnum()) {
+ const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(type);
+ if (metaEnum && metaEnum->isProtected())
+ typeName = protectedEnumSurrogateName(metaEnum);
+ }
+#endif
s << baseConversionString(typeName);
}
diff --git a/shibokengenerator.h b/shibokengenerator.h
index e1dadc86..bb1dcae5 100644
--- a/shibokengenerator.h
+++ b/shibokengenerator.h
@@ -213,6 +213,8 @@ public:
static QString wrapperName(const AbstractMetaClass* metaClass);
+ static QString protectedEnumSurrogateName(const AbstractMetaEnum* metaEnum);
+
static QString pythonPrimitiveTypeName(const QString& cppTypeName);
static QString pythonPrimitiveTypeName(const PrimitiveTypeEntry* type);
diff --git a/tests/libsample/protected.h b/tests/libsample/protected.h
index abbbf293..d8d55a40 100644
--- a/tests/libsample/protected.h
+++ b/tests/libsample/protected.h
@@ -111,6 +111,10 @@ class LIBSAMPLE_API ProtectedEnumClass
public:
ProtectedEnumClass() {}
virtual ~ProtectedEnumClass() {}
+ enum PublicEnum {
+ PublicItem0,
+ PublicItem1
+ };
protected:
enum ProtectedEnum {
ProtectedItem0,
@@ -118,6 +122,8 @@ protected:
};
ProtectedEnum callProtectedEnumMethod(ProtectedEnum in) { return protectedEnumMethod(in); }
virtual ProtectedEnum protectedEnumMethod(ProtectedEnum in) { return in; }
+ PublicEnum callPublicEnumMethod(PublicEnum in) { return publicEnumMethod(in); }
+ virtual PublicEnum publicEnumMethod(PublicEnum in) { return in; }
};
#endif // PROTECTED_H
diff --git a/tests/samplebinding/protected_test.py b/tests/samplebinding/protected_test.py
index 6a5f732c..efb0bedb 100755
--- a/tests/samplebinding/protected_test.py
+++ b/tests/samplebinding/protected_test.py
@@ -185,12 +185,16 @@ class ExtendedProtectedEnumClass(ProtectedEnumClass):
if value == ProtectedEnumClass.ProtectedItem0:
return ProtectedEnumClass.ProtectedItem1
return ProtectedEnumClass.ProtectedItem0
+ def publicEnumMethod(self, value):
+ if value == ProtectedEnumClass.PublicItem0:
+ return ProtectedEnumClass.PublicItem1
+ return ProtectedEnumClass.PublicItem0
class ProtectedEnumTest(unittest.TestCase):
'''Test cases for protected enum.'''
- def testProtectedEnum(self):
- '''Original protected method is being called.'''
+ def testProtectedMethodWithProtectedEnumArgument(self):
+ '''Calls protected method with protected enum argument.'''
obj = ProtectedEnumClass()
self.assertEqual(type(ProtectedEnumClass.ProtectedItem0), ProtectedEnumClass.ProtectedEnum)
@@ -201,8 +205,18 @@ class ProtectedEnumTest(unittest.TestCase):
self.assertEqual(obj.callProtectedEnumMethod(ProtectedEnumClass.ProtectedItem0), ProtectedEnumClass.ProtectedItem0)
self.assertEqual(obj.callProtectedEnumMethod(ProtectedEnumClass.ProtectedItem1), ProtectedEnumClass.ProtectedItem1)
- def testProtectedEnumWithMethodOverride(self):
- '''Overridden protected method is being called.'''
+ def testProtectedMethodWithPublicEnumArgument(self):
+ '''Calls protected method with public enum argument.'''
+ obj = ProtectedEnumClass()
+
+ self.assertEqual(obj.publicEnumMethod(ProtectedEnumClass.PublicItem0), ProtectedEnumClass.PublicItem0)
+ self.assertEqual(obj.publicEnumMethod(ProtectedEnumClass.PublicItem1), ProtectedEnumClass.PublicItem1)
+
+ self.assertEqual(obj.callPublicEnumMethod(ProtectedEnumClass.PublicItem0), ProtectedEnumClass.PublicItem0)
+ self.assertEqual(obj.callPublicEnumMethod(ProtectedEnumClass.PublicItem1), ProtectedEnumClass.PublicItem1)
+
+ def testOverriddenProtectedMethodWithProtectedEnumArgument(self):
+ '''Calls overridden protected method with protected enum argument.'''
obj = ExtendedProtectedEnumClass()
self.assertEqual(obj.protectedEnumMethod(ProtectedEnumClass.ProtectedItem0), ProtectedEnumClass.ProtectedItem1)
@@ -214,6 +228,20 @@ class ProtectedEnumTest(unittest.TestCase):
self.assertEqual(obj.callProtectedEnumMethod(ProtectedEnumClass.ProtectedItem0), ProtectedEnumClass.ProtectedItem1)
self.assertEqual(obj.callProtectedEnumMethod(ProtectedEnumClass.ProtectedItem1), ProtectedEnumClass.ProtectedItem0)
+ def testOverriddenProtectedMethodWithPublicEnumArgument(self):
+ '''Calls overridden protected method with public enum argument.'''
+ obj = ExtendedProtectedEnumClass()
+
+ self.assertEqual(obj.publicEnumMethod(ProtectedEnumClass.PublicItem0), ProtectedEnumClass.PublicItem1)
+ self.assertEqual(obj.publicEnumMethod(ProtectedEnumClass.PublicItem1), ProtectedEnumClass.PublicItem0)
+
+ self.assertEqual(ProtectedEnumClass.publicEnumMethod(obj, ProtectedEnumClass.PublicItem0), ProtectedEnumClass.PublicItem0)
+ self.assertEqual(ProtectedEnumClass.publicEnumMethod(obj, ProtectedEnumClass.PublicItem1), ProtectedEnumClass.PublicItem1)
+
+ self.assertEqual(obj.callPublicEnumMethod(ProtectedEnumClass.PublicItem0), ProtectedEnumClass.PublicItem1)
+ self.assertEqual(obj.callPublicEnumMethod(ProtectedEnumClass.PublicItem1), ProtectedEnumClass.PublicItem0)
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml
index 2a905f23..e53486fc 100644
--- a/tests/samplebinding/typesystem_sample.xml
+++ b/tests/samplebinding/typesystem_sample.xml
@@ -280,9 +280,9 @@
</object-type>
- // Receives and returns the same protected enum item.
<object-type name="ProtectedEnumClass" />
<enum-type name="ProtectedEnumClass::ProtectedEnum" />
+ <enum-type name="ProtectedEnumClass::PublicEnum" />
<template name="boolptr_at_end_fix_beginning">
bool __ok__;