summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2011-08-16 16:03:21 -0300
committerMarcelo Lira <marcelo.lira@openbossa.org>2011-12-09 20:28:06 -0300
commit11eda546a3bc3133ab180c6be5723f10a2abcf22 (patch)
treed5e489f838a9e39e23ebd86c76a023c5c5c03d2f
parent3783e1c72b5497c5564a02308efb0b1fc7d4e224 (diff)
downloadshiboken-11eda546a3bc3133ab180c6be5723f10a2abcf22.tar.gz
shiboken-11eda546a3bc3133ab180c6be5723f10a2abcf22.tar.xz
shiboken-11eda546a3bc3133ab180c6be5723f10a2abcf22.zip
New converters for C++ primitive types.
-rw-r--r--generator/cppgenerator.cpp39
-rw-r--r--generator/headergenerator.cpp2
-rw-r--r--generator/shibokengenerator.cpp148
-rw-r--r--generator/shibokengenerator.h9
-rw-r--r--libshiboken/basewrapper.cpp2
-rw-r--r--libshiboken/sbkconverter.cpp32
-rw-r--r--libshiboken/sbkconverter.h44
-rw-r--r--libshiboken/sbkconverter_p.h367
8 files changed, 591 insertions, 52 deletions
diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp
index 9fe65ca2..cb59b809 100644
--- a/generator/cppgenerator.cpp
+++ b/generator/cppgenerator.cpp
@@ -799,7 +799,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
if (func->type() && func->typeReplaced(0) != "PyObject") {
// TODO-CONVERTER -----------------------------------------------------------------------
- if (isWrapperType(func->type()) || isUserPrimitive(func->type())) {
+ if (func->typeReplaced(0).isEmpty() && (isWrapperType(func->type()) || isUserPrimitive(func->type()) || isCppPrimitive(func->type()))) {
s << INDENT << "PythonToCppFunc " PYTHON_TO_CPP_VAR " = " << cpythonIsConvertibleFunction(func->type());
s << PYTHON_RETURN_VAR ");" << endl;
s << INDENT << "if (!" PYTHON_TO_CPP_VAR ") {" << endl;
@@ -1069,9 +1069,9 @@ void CppGenerator::writeConverterFunctions(QTextStream& s, const AbstractMetaCla
typeCheck = QString("%1(pyIn)").arg(typeCheck);
}
- if (isUserPrimitive(sourceType)) {
+ if (isUserPrimitive(sourceType) || isCppPrimitive(sourceType)) {
QTextStream pc(&toCppPreConv);
- pc << INDENT << getFullTypeNameWithoutModifiers(sourceType) << " cppIn = ";
+ pc << INDENT << getFullTypeNameWithoutModifiers(sourceType) << " cppIn";
writeMinimalConstructorExpression(pc, sourceType);
pc << ';' << endl;
writeToCppConversion(pc, sourceType, 0, "pyIn", "cppIn");
@@ -1079,7 +1079,7 @@ void CppGenerator::writeConverterFunctions(QTextStream& s, const AbstractMetaCla
toCppConv.append("cppIn");
} else if (!isWrapperType(sourceType)) {
QTextStream tcc(&toCppConv);
- writeToCppConversion(tcc, sourceType, metaClass, "pyIn", "/*BOZO-1043*/");
+ writeToCppConversion(tcc, sourceType, metaClass, "pyIn", "/*BOZO-1061*/");
}
// TODO-CONVERTER -----------------------------------------------------------------------
}
@@ -1792,8 +1792,10 @@ void CppGenerator::writeTypeCheck(QTextStream& s, const AbstractMetaType* argTyp
typeCheck.append(QString("(%1)").arg(argumentName));
// TODO-CONVERTER -----------------------------------------------------------------------
- if (customCheck.isEmpty() && (isWrapperType(argType) || isUserPrimitive(argType))) {
+ if (customCheck.isEmpty() && (isWrapperType(argType) || isUserPrimitive(argType) || isCppPrimitive(argType))) {
typeCheck = QString("(%1 = %2))").arg(pythonToCppConverterForArgumentName(argumentName)).arg(typeCheck);
+ if (!isNumber && argType->typeEntry()->isCppPrimitive())
+ typeCheck.prepend(QString("/*BOZOisNumber*/ %1(%2) && ").arg(cpythonCheckFunction(argType)).arg(argumentName));
}
// TODO-CONVERTER -----------------------------------------------------------------------
@@ -1879,16 +1881,17 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream& s,
QString cppOutAux = QString("%1_local").arg(cppOut);
// TODO-CONVERTER -----------------------------------------------------------------------
- if (isWrapperType(type) || isUserPrimitive(type)) {
+ if (isWrapperType(type) || isUserPrimitive(type) || isCppPrimitive(type)) {
bool treatAsPointer = isValueTypeWithCopyConstructorOnly(type);
- bool isPointerOrObjectType = (isObjectType(type) || isPointer(type)) && /*TODO-CONVERTERS: is this really needed?*/ !isUserPrimitive(type);
+ bool isPointerOrObjectType = (isObjectType(type) || isPointer(type)) && /*TODO-CONVERTERS: is this really needed?*/ !isUserPrimitive(type) && !isCppPrimitive(type);
bool mayHaveImplicitConversion = type->isReference()
&& !isUserPrimitive(type)
+ && !isCppPrimitive(type)
&& !(treatAsPointer || isPointerOrObjectType);
QString typeName = getFullTypeNameWithoutModifiers(type);
if (mayHaveImplicitConversion) {
- s << INDENT << typeName << ' ' << cppOutAux << " = ";
+ s << INDENT << typeName << ' ' << cppOutAux;
writeMinimalConstructorExpression(s, type, defaultValue);
s << ';' << endl;
}
@@ -1899,7 +1902,7 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream& s,
} else if (type->isReference() && !type->typeEntry()->isPrimitive()) {
s << "* " << cppOut << " = &" << cppOutAux;
} else {
- s << ' ' << cppOut << " = ";
+ s << ' ' << cppOut;
if (isUserPrimitive(type))
writeMinimalConstructorExpression(s, type->typeEntry(), defaultValue);
else
@@ -1944,7 +1947,7 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream& s,
QString conversion;
QTextStream c(&conversion);
- writeToCppConversion(c, type, context, pyIn, "/*BOZO-1906*/");
+ writeToCppConversion(c, type, context, pyIn, "/*BOZO-1925*/");
// Value type that has default value.
if (type->isValue() && !defaultValue.isEmpty())
@@ -3424,6 +3427,11 @@ void CppGenerator::writeGetterFunction(QTextStream& s, const AbstractMetaField*
cppField.append(')');
}
}
+ if (isCppIntegralPrimitive(fieldType)) {
+ s << getFullTypeNameWithoutModifiers(fieldType) << " cppOut_local = " << cppField << ';' << endl;
+ s << INDENT;
+ cppField = "cppOut_local";
+ }
s << INDENT << "PyObject* pyOut = ";
if (newWrapperSameObject) {
@@ -3459,7 +3467,7 @@ void CppGenerator::writeSetterFunction(QTextStream& s, const AbstractMetaField*
AbstractMetaType* fieldType = metaField->type();
// TODO-CONVERTER -----------------------------------------------------------------------
- if (isWrapperType(fieldType) || isUserPrimitive(fieldType)) {
+ if (isWrapperType(fieldType) || isUserPrimitive(fieldType) || isCppPrimitive(fieldType)) {
s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ';' << endl;
}
// TODO-CONVERTER -----------------------------------------------------------------------
@@ -3476,8 +3484,9 @@ void CppGenerator::writeSetterFunction(QTextStream& s, const AbstractMetaField*
s << INDENT << '}' << endl << endl;
// TODO-CONVERTER -----------------------------------------------------------------------
+ QString cppField = QString("%1->%2").arg(CPP_SELF_VAR).arg(metaField->name());
s << INDENT;
- if (isWrapperType(fieldType) || isUserPrimitive(fieldType)) {
+ if (isWrapperType(fieldType) || isUserPrimitive(fieldType) || isCppPrimitive(fieldType)) {
if (avoidProtectedHack() && metaField->isProtected()) {
s << getFullTypeNameWithoutModifiers(fieldType);
s << (fieldType->indirections() == 1 ? "*" : "") << " cppOut;" << endl;
@@ -3485,8 +3494,12 @@ void CppGenerator::writeSetterFunction(QTextStream& s, const AbstractMetaField*
s << INDENT << QString("((%1*)%2)->%3(cppOut)").arg(wrapperName(metaField->enclosingClass()))
.arg(CPP_SELF_VAR)
.arg(protectedFieldSetterName(metaField));
+ } else if (isCppIntegralPrimitive(fieldType)) {
+ s << getFullTypeNameWithoutModifiers(fieldType) << " cppOut_local = " << cppField << ';' << endl;
+ s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut_local);" << endl;
+ s << INDENT << cppField << " = cppOut_local;" << endl;
} else {
- s << PYTHON_TO_CPP_VAR << QString("(pyIn, &(%1->%2))").arg(CPP_SELF_VAR).arg(metaField->name());
+ s << PYTHON_TO_CPP_VAR << "(pyIn, &(" << cppField << "))";
}
} else { // TODO-CONVERTER --------------------------------------------------------------
QString conversion;
diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp
index e6668853..2b32138f 100644
--- a/generator/headergenerator.cpp
+++ b/generator/headergenerator.cpp
@@ -595,7 +595,7 @@ void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* ty
s << '{' << endl;
s << INDENT << "PythonToCppFunc toCpp = Shiboken::Conversions::isPythonToCppValueConvertible((SbkObjectType*)";
s << cpythonTypeNameExt(type) << ", pyIn);" << endl;
- s << INDENT << typeName << " cppOut = ";
+ s << INDENT << typeName << " cppOut";
writeMinimalConstructorExpression(s, type);
s << ';' << endl;
s << INDENT << "toCpp(pyIn, &cppOut);" << endl;
diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp
index 19a8f7da..e8297d30 100644
--- a/generator/shibokengenerator.cpp
+++ b/generator/shibokengenerator.cpp
@@ -84,8 +84,10 @@ ShibokenGenerator::ShibokenGenerator() : Generator()
m_typeSystemConvRegEx[TypeSystemCheckFunction] = QRegExp("%CHECKTYPE\\[([^\\[]*)\\]\\(");
m_typeSystemConvRegEx[TypeSystemIsConvertibleFunction] = QRegExp("%ISCONVERTIBLE\\[([^\\[]*)\\]\\(");
m_typeSystemConvRegEx[TypeSystemToPythonFunction] = QRegExp("%CONVERTTOPYTHON\\[([^\\[]*)\\]\\(");
- m_typeSystemConvRegEx[TypeSystemToCppFunction] = QRegExp("((?:[a-zA-Z_%][\\w%]*\\s*[\\*&]?\\s+)*)((?:\\*\\s*)?[a-zA-Z_%][\\w%]*"\
- "(?:\\[[^\\[]+\\])*)(?:\\s+)=(?:\\s+)%CONVERTTOCPP\\[([^\\[]*)\\]\\(");
+ m_typeSystemConvRegEx[TypeSystemToCppFunction] = QRegExp("(\\s*//[^\\n]*\\n\\s*)*"
+ "((?:[a-zA-Z_%][\\w%]*\\s*[\\*&]?\\s+)*)"
+ "((?:\\*\\s*)?[a-zA-Z_%][\\w%]*(?:\\[[^\\[]+\\])*)"
+ "(?:\\s+)=(?:\\s+)%CONVERTTOCPP\\[([^\\[]*)\\]\\(");
}
ShibokenGenerator::~ShibokenGenerator()
@@ -121,7 +123,9 @@ void ShibokenGenerator::initPrimitiveTypesCorrespondences()
m_pythonPrimitiveTypeName["short"] = "PyInt";
m_pythonPrimitiveTypeName["ushort"] = "PyInt";
m_pythonPrimitiveTypeName["signed short"] = "PyInt";
+ m_pythonPrimitiveTypeName["signed short int"] = "PyInt";
m_pythonPrimitiveTypeName["unsigned short"] = "PyInt";
+ m_pythonPrimitiveTypeName["unsigned short int"] = "PyInt";
m_pythonPrimitiveTypeName["long"] = "PyInt";
// PyFloat
@@ -591,7 +595,7 @@ void ShibokenGenerator::writeToPythonConversion(QTextStream& s, const AbstractMe
const AbstractMetaClass* context, const QString& argumentName)
{
// TODO-CONVERTER -----------------------------------------------------------------------
- if (isWrapperType(type) || isUserPrimitive(type)) {
+ if (isWrapperType(type) || isUserPrimitive(type) || isCppPrimitive(type)) {
s << cpythonToPythonConversionFunction(type) << argumentName << ')';
return;
}
@@ -612,7 +616,7 @@ void ShibokenGenerator::writeToCppConversion(QTextStream& s, const AbstractMetaT
const QString& inArgName, const QString& outArgName)
{
// TODO-CONVERTER -----------------------------------------------------------------------
- if (isWrapperType(type) || isUserPrimitive(type)) {
+ if (isWrapperType(type) || isUserPrimitive(type) || isCppPrimitive(type)) {
s << cpythonToCppConversionFunction(type, context) << inArgName << ", &" << outArgName << ')';
return;
}
@@ -766,11 +770,18 @@ QString ShibokenGenerator::cpythonTypeNameExt(const TypeEntry* type)
QString ShibokenGenerator::converterObject(const AbstractMetaType* type)
{
+ if (isCString(type))
+ return "Shiboken::Conversions::PrimitiveTypeConverter<const char*>()";
+ if (isVoidPointer(type))
+ return "Shiboken::Conversions::PrimitiveTypeConverter<void*>()";
return converterObject(type->typeEntry());
}
QString ShibokenGenerator::converterObject(const TypeEntry* type)
{
- return convertersVariableName(type->targetLangPackage()) + '[' + getTypeIndexVariableName(type) + ']';
+ if (isCppPrimitive(type))
+ return QString("Shiboken::Conversions::PrimitiveTypeConverter<%1>()").arg(type->qualifiedCppName());
+ QString converters;
+ return QString("%1[%2]").arg(convertersVariableName(type->targetLangPackage())).arg(getTypeIndexVariableName(type));
}
QString ShibokenGenerator::cpythonTypeNameExt(const AbstractMetaType* type)
@@ -904,6 +915,13 @@ bool ShibokenGenerator::isCString(const AbstractMetaType* type)
&& type->name() == "char";
}
+bool ShibokenGenerator::isVoidPointer(const AbstractMetaType* type)
+{
+ return type->isNativePointer()
+ && type->indirections() == 1
+ && type->name() == "void";
+}
+
bool ShibokenGenerator::isPairContainer(const AbstractMetaType* type)
{
return type->isContainer()
@@ -972,6 +990,27 @@ bool ShibokenGenerator::isUserPrimitive(const AbstractMetaType* type)
return isUserPrimitive(type->typeEntry());
}
+bool ShibokenGenerator::isCppPrimitive(const TypeEntry* type)
+{
+ if (type->isCppPrimitive())
+ return true;
+ if (!type->isPrimitive())
+ return false;
+ const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type;
+ if (trueType->basicAliasedTypeEntry())
+ trueType = trueType->basicAliasedTypeEntry();
+ return trueType->qualifiedCppName() == "std::string";
+}
+
+bool ShibokenGenerator::isCppPrimitive(const AbstractMetaType* type)
+{
+ if (isCString(type) || isVoidPointer(type))
+ return true;
+ if (type->indirections() != 0)
+ return false;
+ return isCppPrimitive(type->typeEntry());
+}
+
bool ShibokenGenerator::shouldDereferenceArgumentPointer(const AbstractMetaArgument* arg)
{
return shouldDereferenceAbstractMetaTypePointer(arg->type());
@@ -1004,8 +1043,15 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType
}
// TODO-CONVERTER -----------------------------------------------------------------------
- if (isWrapperType(metaType) || isUserPrimitive(metaType))
+ if (isCppPrimitive(metaType)) {
+ if (isCString(metaType))
+ return "SbkString_Check";
+ if (isVoidPointer(metaType))
+ return "PyObject_Check";
return cpythonCheckFunction(metaType->typeEntry(), genericNumberType);
+ } else if (isWrapperType(metaType) || isUserPrimitive(metaType)) {
+ return cpythonCheckFunction(metaType->typeEntry(), genericNumberType);
+ }
// TODO-CONVERTER -----------------------------------------------------------------------
QString baseName = cpythonBaseName(metaType);
@@ -1036,6 +1082,8 @@ QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry* type, bool gene
// TODO-CONVERTER -----------------------------------------------------------------------
if (isWrapperType(type)) {
return QString("SbkObject_TypeCheck(%1, ").arg(cpythonTypeNameExt(type));
+ } else if (isCppPrimitive(type)) {
+ return QString("%1_Check").arg(pythonPrimitiveTypeName((const PrimitiveTypeEntry*)type));
} else if (isUserPrimitive(type)) {
QString typeCheck;
if (!type->targetLangApiName().isEmpty())
@@ -1094,7 +1142,7 @@ QString ShibokenGenerator::cpythonIsConvertibleFunction(const TypeEntry* type, b
: "isPythonToCppPointerConvertible";
return QString("Shiboken::Conversions::%1((SbkObjectType*)%2, ")
.arg(isConv).arg(cpythonTypeNameExt(type));
- } else if (isUserPrimitive(type)) {
+ } else if (isUserPrimitive(type) || isCppPrimitive(type)) {
return QString("Shiboken::Conversions::isPythonToCppConvertible(%1, ")
.arg(converterObject(type));
}
@@ -1134,7 +1182,7 @@ QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaType*
isConv = "isPythonToCppValueConvertible";
return QString("Shiboken::Conversions::%1((SbkObjectType*)%2, ")
.arg(isConv).arg(cpythonTypeNameExt(metaType));
- } else if (isUserPrimitive(metaType)) {
+ } else if (isUserPrimitive(metaType) || isCppPrimitive(metaType)) {
return QString("Shiboken::Conversions::isPythonToCppConvertible(%1, ")
.arg(converterObject(metaType));
}
@@ -1168,7 +1216,7 @@ QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaType
return QString("Shiboken::Conversions::pythonToCpp%1((SbkObjectType*)%2, ")
.arg(isPointer(type) ? "Pointer" : "Copy")
.arg(cpythonTypeNameExt(type));
- } else if (isUserPrimitive(type)) {
+ } else if (isUserPrimitive(type) || isCppPrimitive(type)) {
return QString("Shiboken::Conversions::pythonToCpp(%1, ")
.arg(converterObject(type));
}
@@ -1192,8 +1240,10 @@ QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaT
conversion = "pointer";
return QString("Shiboken::Conversions::%1ToPython((SbkObjectType*)%2, %3")
.arg(conversion).arg(cpythonTypeNameExt(type)).arg(conversion == "pointer" ? "" : "&");
- } else if (isUserPrimitive(type)) {
- return QString("Shiboken::Conversions::copyToPython(%1, &").arg(converterObject(type));
+ } else if (isUserPrimitive(type) || isCppPrimitive(type)) {
+ return QString("Shiboken::Conversions::copyToPython(%1, %2")
+ .arg(converterObject(type))
+ .arg((isCString(type) || isVoidPointer(type)) ? "" : "&");
}
// TODO-CONVERTER -----------------------------------------------------------------------
// exclude const on Objects
@@ -1220,7 +1270,7 @@ QString ShibokenGenerator::cpythonToPythonConversionFunction(const TypeEntry* ty
conversion = "pointer";
return QString("Shiboken::Conversions::%1ToPython((SbkObjectType*)%2, %3")
.arg(conversion).arg(cpythonTypeNameExt(type)).arg(conversion == "pointer" ? "" : "&");
- } else if (isUserPrimitive(type)) {
+ } else if (isUserPrimitive(type) || isCppPrimitive(type)) {
return QString("Shiboken::Conversions::copyToPython(%1, &").arg(converterObject(type));
}
// TODO-CONVERTER -----------------------------------------------------------------------
@@ -1784,10 +1834,13 @@ static bool isVariable(const QString& code)
static QString miniNormalizer(const QString& varType)
{
QString normalized = varType.trimmed();
+ if (normalized.isEmpty())
+ return normalized;
QString suffix;
while (normalized.endsWith('*') || normalized.endsWith('&')) {
suffix.prepend(normalized.at(normalized.count() - 1));
normalized.chop(1);
+ normalized = normalized.trimmed();
}
return QString("%1 %2").arg(normalized).arg(suffix).trimmed();
}
@@ -1834,20 +1887,21 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
if (conversionType) {
switch (converterVariable) {
case TypeSystemToCppFunction: {
- if (!isWrapperType(conversionType) && !isUserPrimitive(conversionType)) {
- c << list.at(1) << list.at(2) << " = ";
+ c << list.at(1);
+ if (!isWrapperType(conversionType) && !isUserPrimitive(conversionType) && !isCppPrimitive(conversionType)) {
+ c << list.at(2) << list.at(3) << " = ";
c << cpythonToCppConversionFunction(conversionType);
c << '(';
break;
}
- QString varType = miniNormalizer(list.at(1));
- QString varName = list.at(2).trimmed();
+ QString varType = miniNormalizer(list.at(2));
+ QString varName = list.at(3).trimmed();
if (!varType.isEmpty()) {
if (varType != conversionType->cppSignature()) {
qFatal(qPrintable(QString("Types of receiver variable ('%1') and %CONVERTTOCPP type system variable ('%2') differ.")
.arg(varType).arg(conversionType->cppSignature())), NULL);
}
- c << getFullTypeName(conversionType) << ' ' << varName << " = ";
+ c << getFullTypeName(conversionType) << ' ' << varName;
writeMinimalConstructorExpression(c, conversionType);
c << ';' << endl;
Indentation indent(INDENT);
@@ -1856,7 +1910,7 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
c << cpythonToCppConversionFunction(conversionType);
QString prefix;
if (varName.startsWith('*')) {
- varName.chop(1);
+ varName.remove(0, 1);
varName = varName.trimmed();
} else {
prefix = '&';
@@ -1876,7 +1930,7 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
conversion = cpythonToPythonConversionFunction(conversionType);
default: {
// TODO-CONVERTER -----------------------------------------------------------------------
- if (!isWrapperType(conversionType) && !isUserPrimitive(conversionType)) {
+ if (!isWrapperType(conversionType) && !isUserPrimitive(conversionType) && !isCppPrimitive(conversionType)) {
c << '(';
break;
}
@@ -1898,8 +1952,8 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
}
}
} else {
- if (list.count() > 2)
- c << list.at(1) << list.at(2) << " = ";
+ if (list.count() > 3)
+ c << list.at(2) << list.at(3) << " = ";
c << QString("Shiboken::Converter< %1 >::%2(").arg(conversionTypeName).arg(conversionName);
}
replacements.append(qMakePair(conversionString, conversion));
@@ -2322,6 +2376,11 @@ QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClass* met
}
QString ShibokenGenerator::getTypeIndexVariableName(const TypeEntry* type)
{
+ if (type->isCppPrimitive()) {
+ const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type;
+ if (trueType->basicAliasedTypeEntry())
+ type = trueType->basicAliasedTypeEntry();
+ }
return QString("SBK_%1_IDX").arg(_fixedCppTypeName(type->qualifiedCppName()).toUpper());
}
QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaType* type)
@@ -2336,7 +2395,9 @@ QString ShibokenGenerator::getFullTypeName(const TypeEntry* type)
QString ShibokenGenerator::getFullTypeName(const AbstractMetaType* type)
{
if (isCString(type))
- return QString("const char*");
+ return "const char*";
+ if (isVoidPointer(type))
+ return "void*";
return getFullTypeName(type->typeEntry()) + QString("*").repeated(type->indirections());
}
QString ShibokenGenerator::getFullTypeName(const AbstractMetaClass* metaClass)
@@ -2345,6 +2406,10 @@ QString ShibokenGenerator::getFullTypeName(const AbstractMetaClass* metaClass)
}
QString ShibokenGenerator::getFullTypeNameWithoutModifiers(const AbstractMetaType* type)
{
+ if (isCString(type))
+ return "const char*";
+ if (isVoidPointer(type))
+ return "void*";
if (!type->hasInstantiations())
return getFullTypeName(type->typeEntry());
QString typeName = type->cppSignature();
@@ -2411,24 +2476,35 @@ QString ShibokenGenerator::getDefaultValue(const AbstractMetaFunction* func, co
// TODO-CONVERTER -----------------------------------------------------------------------
void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream& s, const AbstractMetaType* type, const QString& defaultCtor)
{
- QString ctor = defaultCtor.isEmpty() ? minimalConstructor(type) : defaultCtor;
- if (ctor.isEmpty()) {
- QString errorMsg = QString(MIN_CTOR_ERROR_MSG).arg(type->cppSignature());
- ReportHandler::warning(errorMsg);
- s << endl << INDENT << "#error " << errorMsg << endl;
+ if (defaultCtor.isEmpty() && isCppPrimitive(type))
return;
- }
- s << ctor;
+ QString ctor = defaultCtor.isEmpty() ? minimalConstructor(type) : defaultCtor;
+ if (ctor.isEmpty())
+ qFatal(qPrintable(QString(MIN_CTOR_ERROR_MSG).arg(type->cppSignature())), NULL);
+ s << " = " << ctor;
}
void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream& s, const TypeEntry* type, const QString& defaultCtor)
{
- QString ctor = defaultCtor.isEmpty() ? minimalConstructor(type) : defaultCtor;
- if (ctor.isEmpty()) {
- QString errorMsg = QString(MIN_CTOR_ERROR_MSG).arg(type->qualifiedCppName());
- ReportHandler::warning(errorMsg);
- s << endl << INDENT << "#error " << errorMsg << endl;
+ if (defaultCtor.isEmpty() && isCppPrimitive(type))
return;
- }
- s << ctor;
+ QString ctor = defaultCtor.isEmpty() ? minimalConstructor(type) : defaultCtor;
+ if (ctor.isEmpty())
+ qFatal(qPrintable(QString(MIN_CTOR_ERROR_MSG).arg(type->qualifiedCppName())), NULL);
+ s << " = " << ctor;
+}
+
+bool ShibokenGenerator::isCppIntegralPrimitive(const TypeEntry* type)
+{
+ if (!type->isCppPrimitive())
+ return false;
+ const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type;
+ if (trueType->basicAliasedTypeEntry())
+ trueType = trueType->basicAliasedTypeEntry();
+ QString typeName = trueType->qualifiedCppName();
+ return !typeName.contains("double") && !typeName.contains("float") && !typeName.contains("wchar");
+}
+bool ShibokenGenerator::isCppIntegralPrimitive(const AbstractMetaType* type)
+{
+ return isCppIntegralPrimitive(type->typeEntry());
}
// TODO-CONVERTER -----------------------------------------------------------------------
diff --git a/generator/shibokengenerator.h b/generator/shibokengenerator.h
index 00de9586..8cd91c2e 100644
--- a/generator/shibokengenerator.h
+++ b/generator/shibokengenerator.h
@@ -289,6 +289,7 @@ public:
static bool isPyInt(const TypeEntry* type);
static bool isPyInt(const AbstractMetaType* type);
static bool isCString(const AbstractMetaType* type);
+ static bool isVoidPointer(const AbstractMetaType* type);
static bool isPairContainer(const AbstractMetaType* type);
/**
@@ -313,6 +314,14 @@ public:
static bool isUserPrimitive(const TypeEntry* type);
static bool isUserPrimitive(const AbstractMetaType* type);
+ /// Returns true if the type is a C++ primitive, a void*, a const char*, or a std::string.
+ static bool isCppPrimitive(const TypeEntry* type);
+ static bool isCppPrimitive(const AbstractMetaType* type);
+
+ /// Returns true if the type is a C++ integral primitive, i.e. bool, char, int, long, and their unsigned counterparts.
+ static bool isCppIntegralPrimitive(const TypeEntry* type);
+ static bool isCppIntegralPrimitive(const AbstractMetaType* type);
+
/// Checks if an argument type should be dereferenced by the Python method wrapper before calling the C++ method.
static bool shouldDereferenceArgumentPointer(const AbstractMetaArgument* arg);
/// Checks if a meta type should be dereferenced by the Python method wrapper passing it to C++.
diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp
index 181b7025..fc83d44c 100644
--- a/libshiboken/basewrapper.cpp
+++ b/libshiboken/basewrapper.cpp
@@ -462,6 +462,7 @@ void DeallocVisitor::done()
}
namespace Module { void init(); }
+namespace Conversions { void init(); }
void init()
{
@@ -470,6 +471,7 @@ void init()
return;
Module::init();
+ Conversions::init();
initTypeResolver();
PyEval_InitThreads();
diff --git a/libshiboken/sbkconverter.cpp b/libshiboken/sbkconverter.cpp
index c5e64f3d..34705d9e 100644
--- a/libshiboken/sbkconverter.cpp
+++ b/libshiboken/sbkconverter.cpp
@@ -26,9 +26,35 @@
#include "sbkdbg.h"
+static SbkConverter** PrimitiveTypeConverters;
+
namespace Shiboken {
namespace Conversions {
+void init()
+{
+ static SbkConverter* primitiveTypeConverters[] = {
+ Primitive<PY_LONG_LONG>::createConverter(),
+ Primitive<bool>::createConverter(),
+ Primitive<char>::createConverter(),
+ Primitive<const char*>::createConverter(),
+ Primitive<double>::createConverter(),
+ Primitive<float>::createConverter(),
+ Primitive<int>::createConverter(),
+ Primitive<long>::createConverter(),
+ Primitive<short>::createConverter(),
+ Primitive<signed char>::createConverter(),
+ Primitive<std::string>::createConverter(),
+ Primitive<unsigned PY_LONG_LONG>::createConverter(),
+ Primitive<unsigned char>::createConverter(),
+ Primitive<unsigned int>::createConverter(),
+ Primitive<unsigned long>::createConverter(),
+ Primitive<unsigned short>::createConverter(),
+ Primitive<void*>::createConverter()
+ };
+ PrimitiveTypeConverters = primitiveTypeConverters;
+}
+
static SbkConverter* createConverterObject(PyTypeObject* type,
PythonToCppFunc toCppPointerConvFunc,
IsConvertibleToCppFunc toCppPointerCheckFunc,
@@ -113,7 +139,6 @@ PyObject* referenceToPython(SbkObjectType* type, const void* cppIn)
static inline PyObject* CopyCppToPython(SbkConverter* converter, const void* cppIn)
{
- assert(cppIn);
return converter->copyToPython(cppIn);
}
PyObject* copyToPython(SbkObjectType* type, const void* cppIn)
@@ -228,4 +253,9 @@ bool isImplicitConversion(SbkObjectType* type, PythonToCppFunc toCppFunc)
return toCppFunc != (*conv).second;
}
+SbkConverter* primitiveTypeConverter(int index)
+{
+ return PrimitiveTypeConverters[index];
+}
+
} } // namespace Shiboken::Conversions
diff --git a/libshiboken/sbkconverter.h b/libshiboken/sbkconverter.h
index 1d539248..6c10df2a 100644
--- a/libshiboken/sbkconverter.h
+++ b/libshiboken/sbkconverter.h
@@ -36,6 +36,8 @@
#define SbkObject_TypeCheck(tp, ob) \
(Py_TYPE(ob) == (tp) || PyType_IsSubtype(Py_TYPE(ob), (tp)))
+#define SbkString_Check(pyObj) (pyObj == Py_None || PyString_Check(pyObj))
+
extern "C"
{
@@ -83,7 +85,6 @@ typedef PythonToCppFunc (*IsConvertibleToCppFunc)(PyObject*);
} // extern "C"
-
namespace Shiboken {
namespace Conversions {
@@ -211,6 +212,47 @@ LIBSHIBOKEN_API void nonePythonToCppNullPtr(PyObject*, void* cppOut);
*/
LIBSHIBOKEN_API bool isImplicitConversion(SbkObjectType* type, PythonToCppFunc toCpp);
+/// Returns the converter for a primitive type.
+LIBSHIBOKEN_API SbkConverter* primitiveTypeConverter(int index);
+
+#define SBK_PY_LONG_LONG_IDX 0
+#define SBK_BOOL_IDX 1
+#define SBK_CHAR_IDX 2
+#define SBK_CONSTCHARPTR_IDX 3
+#define SBK_DOUBLE_IDX 4
+#define SBK_FLOAT_IDX 5
+#define SBK_INT_IDX 6
+#define SBK_SIGNEDINT_IDX 6
+#define SBK_LONG_IDX 7
+#define SBK_SHORT_IDX 8
+#define SBK_SIGNEDCHAR_IDX 9
+#define SBK_STD_STRING_IDX 10
+#define SBK_UNSIGNEDPY_LONG_LONG_IDX 11
+#define SBK_UNSIGNEDCHAR_IDX 12
+#define SBK_UNSIGNEDINT_IDX 13
+#define SBK_UNSIGNEDLONG_IDX 14
+#define SBK_UNSIGNEDSHORT_IDX 15
+#define SBK_VOIDPTR_IDX 16
+
+template<typename T> SbkConverter* PrimitiveTypeConverter() { return 0; }
+template<> inline SbkConverter* PrimitiveTypeConverter<PY_LONG_LONG>() { return primitiveTypeConverter(SBK_PY_LONG_LONG_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<bool>() { return primitiveTypeConverter(SBK_BOOL_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<char>() { return primitiveTypeConverter(SBK_CHAR_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<const char*>() { return primitiveTypeConverter(SBK_CONSTCHARPTR_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<double>() { return primitiveTypeConverter(SBK_DOUBLE_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<float>() { return primitiveTypeConverter(SBK_FLOAT_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<int>() { return primitiveTypeConverter(SBK_INT_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<long>() { return primitiveTypeConverter(SBK_LONG_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<short>() { return primitiveTypeConverter(SBK_SHORT_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<signed char>() { return primitiveTypeConverter(SBK_SIGNEDCHAR_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<std::string>() { return primitiveTypeConverter(SBK_STD_STRING_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<unsigned PY_LONG_LONG>() { return primitiveTypeConverter(SBK_UNSIGNEDPY_LONG_LONG_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<unsigned char>() { return primitiveTypeConverter(SBK_UNSIGNEDCHAR_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<unsigned int>() { return primitiveTypeConverter(SBK_UNSIGNEDINT_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<unsigned long>() { return primitiveTypeConverter(SBK_UNSIGNEDLONG_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<unsigned short>() { return primitiveTypeConverter(SBK_UNSIGNEDSHORT_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<void*>() { return primitiveTypeConverter(SBK_VOIDPTR_IDX); }
+
} } // namespace Shiboken::Conversions
#endif // SBK_CONVERTER_H
diff --git a/libshiboken/sbkconverter_p.h b/libshiboken/sbkconverter_p.h
index 199538cc..8abdc297 100644
--- a/libshiboken/sbkconverter_p.h
+++ b/libshiboken/sbkconverter_p.h
@@ -25,8 +25,11 @@
#include <Python.h>
#include <list>
+#include <limits>
#include "sbkconverter.h"
+#include "sbkdbg.h"
+
extern "C"
{
@@ -87,4 +90,368 @@ struct SbkConverter
} // extern "C"
+// Helper template for checking if a value overflows when cast to type T.
+template<typename T, bool isSigned = std::numeric_limits<T>::is_signed >
+struct OverFlowChecker;
+
+template<typename T>
+struct OverFlowChecker<T, true> {
+ static bool check(const PY_LONG_LONG& value) {
+ return value < std::numeric_limits<T>::min() || value > std::numeric_limits<T>::max();
+ }
+};
+template<typename T>
+struct OverFlowChecker<T, false> {
+ static bool check(const PY_LONG_LONG& value) {
+ return value < 0 || static_cast<unsigned long long>(value) > std::numeric_limits<T>::max();
+ }
+};
+template<>
+struct OverFlowChecker<PY_LONG_LONG, true> {
+ static bool check(const PY_LONG_LONG& value) { return false; }
+};
+template<>
+struct OverFlowChecker<double, true> {
+ static bool check(const double& value) { return false; }
+};
+template<>
+struct OverFlowChecker<float, true> {
+ static bool check(const double& value) {
+ return value < std::numeric_limits<float>::min() || value > std::numeric_limits<float>::max();
+ }
+};
+
+// Basic primitive type converters ---------------------------------------------------------
+template<typename T> PyTypeObject* SbkType() { return 0; }
+template<> inline PyTypeObject* SbkType<PY_LONG_LONG>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<bool>() { return &PyBool_Type; }
+template<> inline PyTypeObject* SbkType<char>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<const char*>() { return &PyString_Type; }
+template<> inline PyTypeObject* SbkType<double>() { return &PyFloat_Type; }
+template<> inline PyTypeObject* SbkType<float>() { return &PyFloat_Type; }
+template<> inline PyTypeObject* SbkType<int>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<long>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<short>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<signed char>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<unsigned PY_LONG_LONG>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<unsigned char>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<unsigned int>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<unsigned long>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<unsigned short>() { return &PyInt_Type; }
+
+template <typename T> struct Primitive {};
+
+template <typename T>
+struct OnePrimitive
+{
+ static PyObject* toPython(const void*) { return 0; }
+ static PythonToCppFunc isConvertible(PyObject*) { return 0; }
+ static void toCpp(PyObject*, void*) {}
+ static SbkConverter* createConverter()
+ {
+ SbkConverter* converter = Shiboken::Conversions::createConverter(SbkType<T>(), Primitive<T>::toPython);
+ Shiboken::Conversions::addPythonToCppValueConversion(converter, Primitive<T>::toCpp, Primitive<T>::isConvertible);
+ return converter;
+ }
+};
+template <typename T>
+struct TwoPrimitive : OnePrimitive<T>
+{
+ static PythonToCppFunc isOtherConvertible(PyObject*) { return 0; }
+ static void otherToCpp(PyObject*, void*) {}
+ static SbkConverter* createConverter()
+ {
+ SbkConverter* converter = OnePrimitive<T>::createConverter();
+ Shiboken::Conversions::addPythonToCppValueConversion(converter, Primitive<T>::otherToCpp, Primitive<T>::isOtherConvertible);
+ return converter;
+ }
+};
+
+// 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 <typename INT>
+struct IntPrimitive : TwoPrimitive<INT>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return PyInt_FromLong((long)*((INT*)cppIn));
+ }
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ double result = PyFloat_AS_DOUBLE(pyIn);
+ // If cast to long directly it could overflow silently.
+ if (OverFlowChecker<INT>::check(result))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ *((INT*)cppOut) = static_cast<INT>(result);
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ if (PyFloat_Check(pyIn))
+ return toCpp;
+ return 0;
+ }
+ static void otherToCpp(PyObject* pyIn, void* cppOut)
+ {
+ PY_LONG_LONG result = PyLong_AsLongLong(pyIn);
+ if (OverFlowChecker<INT>::check(result))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ *((INT*)cppOut) = static_cast<INT>(result);
+ }
+ static PythonToCppFunc isOtherConvertible(PyObject* pyIn)
+ {
+ if (SbkNumber_Check(pyIn))
+ return otherToCpp;
+ return 0;
+ }
+};
+template <> struct Primitive<int> : IntPrimitive<int> {};
+template <> struct Primitive<long> : IntPrimitive<long> {};
+template <> struct Primitive<short> : IntPrimitive<short> {};
+template <> struct Primitive<unsigned short> : IntPrimitive<unsigned short> {};
+
+// Unsigned Long Integers ------------------------------------------------------------------
+
+template <typename LONG>
+struct UnsignedLongPrimitive : IntPrimitive<LONG>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return PyLong_FromUnsignedLong(*((LONG*)cppIn));
+ }
+};
+template <> struct Primitive<unsigned int> : UnsignedLongPrimitive<unsigned int> {};
+template <> struct Primitive<unsigned long> : UnsignedLongPrimitive<unsigned long> {};
+
+// Big integers ----------------------------------------------------------------------------
+
+template <>
+struct Primitive<PY_LONG_LONG> : OnePrimitive<PY_LONG_LONG>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return PyLong_FromLongLong(*((PY_LONG_LONG*)cppIn));
+ }
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ *((PY_LONG_LONG*)cppOut) = (PY_LONG_LONG) PyLong_AsLongLong(pyIn);
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ if (SbkNumber_Check(pyIn))
+ return toCpp;
+ return 0;
+ }
+};
+
+template <>
+struct Primitive<unsigned PY_LONG_LONG> : OnePrimitive<unsigned PY_LONG_LONG>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return PyLong_FromUnsignedLongLong(*((unsigned PY_LONG_LONG*)cppIn));
+ }
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ *((unsigned PY_LONG_LONG*)cppOut) = (unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLong(pyIn);
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ if (SbkNumber_Check(pyIn))
+ return toCpp;
+ return 0;
+ }
+};
+
+// Floating point --------------------------------------------------------------------------
+
+template <typename FLOAT>
+struct FloatPrimitive : TwoPrimitive<FLOAT>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return PyFloat_FromDouble((double)*((FLOAT*)cppIn));
+ }
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ *((FLOAT*)cppOut) = (FLOAT) PyLong_AsLong(pyIn);
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ if (PyInt_Check(pyIn) || PyLong_Check(pyIn))
+ return toCpp;
+ return 0;
+ }
+ static void otherToCpp(PyObject* pyIn, void* cppOut)
+ {
+ *((FLOAT*)cppOut) = (FLOAT) PyFloat_AsDouble(pyIn);
+ }
+ static PythonToCppFunc isOtherConvertible(PyObject* pyIn)
+ {
+ if (SbkNumber_Check(pyIn))
+ return otherToCpp;
+ return 0;
+ }
+};
+template <> struct Primitive<float> : FloatPrimitive<float> {};
+template <> struct Primitive<double> : FloatPrimitive<double> {};
+
+// Boolean ---------------------------------------------------------------------------------
+
+template <>
+struct Primitive<bool> : OnePrimitive<bool>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return PyBool_FromLong(*((bool*)cppIn));
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ if (SbkNumber_Check(pyIn))
+ return toCpp;
+ return 0;
+ }
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ *((bool*)cppOut) = (bool) PyInt_AS_LONG(pyIn);
+ }
+};
+
+// Characters ------------------------------------------------------------------------------
+
+template <typename CHAR>
+struct CharPrimitive : IntPrimitive<CHAR>
+{
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ *((CHAR*)cppOut) = (CHAR) PyString_AS_STRING(pyIn)[0];
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ if (PyString_Check(pyIn) && PyString_Size(pyIn) == 1)
+ return toCpp;
+ return 0;
+ }
+ static void otherToCpp(PyObject* pyIn, void* cppOut)
+ {
+ PY_LONG_LONG result = PyLong_AsLongLong(pyIn);
+ if (OverFlowChecker<CHAR>::check(result))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ *((CHAR*)cppOut) = (CHAR) result;
+ }
+ static PythonToCppFunc isOtherConvertible(PyObject* pyIn)
+ {
+ if (SbkNumber_Check(pyIn))
+ return otherToCpp;
+ return 0;
+ }
+ static SbkConverter* createConverter()
+ {
+ SbkConverter* converter = IntPrimitive<CHAR>::createConverter();
+ Shiboken::Conversions::addPythonToCppValueConversion(converter, CharPrimitive<CHAR>::otherToCpp, CharPrimitive<CHAR>::isOtherConvertible);
+ return converter;
+ }
+
+};
+template <> struct Primitive<signed char> : CharPrimitive<signed char> {};
+template <> struct Primitive<unsigned char> : CharPrimitive<unsigned char> {};
+template <> struct Primitive<char> : CharPrimitive<char> {
+ using CharPrimitive<char>::toPython;
+ static PyObject* toPython(const void* cppIn) {
+ return PyString_FromFormat("%c", *((const char*)cppIn));
+ }
+};
+
+
+
+// Strings ---------------------------------------------------------------------------------
+
+template <>
+struct Primitive<const char*> : TwoPrimitive<const char*>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ if (!cppIn)
+ Py_RETURN_NONE;
+ return PyString_FromString((const char*)cppIn);
+ }
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ *((const char**)cppOut) = 0;
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ if (pyIn == Py_None)
+ return toCpp;
+ return 0;
+ }
+ static void otherToCpp(PyObject* pyIn, void* cppOut)
+ {
+ *((const char**)cppOut) = (const char*) PyString_AsString(pyIn);
+ }
+ static PythonToCppFunc isOtherConvertible(PyObject* pyIn)
+ {
+ if (PyString_Check(pyIn))
+ return otherToCpp;
+ return 0;
+ }
+};
+
+template <>
+struct Primitive<std::string> : TwoPrimitive<std::string>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return PyString_FromString(((std::string*)cppIn)->c_str());
+ }
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ *((std::string*)cppOut) = std::string();
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ if (pyIn == Py_None)
+ return toCpp;
+ return 0;
+ }
+ static void otherToCpp(PyObject* pyIn, void* cppOut)
+ {
+ *((std::string*)cppOut) = std::string(PyString_AsString(pyIn));
+ }
+ static PythonToCppFunc isOtherConvertible(PyObject* pyIn)
+ {
+ if (PyString_Check(pyIn))
+ return otherToCpp;
+ return 0;
+ }
+};
+
+// Void pointer ----------------------------------------------------------------------------
+
+template <>
+struct Primitive<void*> : OnePrimitive<void*>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ SbkDbg() << cppIn;
+ if (!cppIn)
+ Py_RETURN_NONE;
+ PyObject* result = (PyObject*) cppIn;
+ Py_INCREF(result);
+ return result;
+ }
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ SbkDbg() << pyIn;
+ *((void**)cppOut) = pyIn;
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ return toCpp;
+ }
+};
+
#endif // SBK_CONVERTER_P_H