Commit e4f3a9a5 authored by Ghislain MARY's avatar Ghislain MARY

Support C++ wrapper generation with Python 3.

parent 274ff16b
......@@ -175,7 +175,6 @@ if(ENABLE_LIME)
set(HAVE_LIME 1)
endif()
if(ENABLE_CXX_WRAPPER)
set(Python_ADDITIONAL_VERSIONS 2)
find_package(PythonInterp REQUIRED)
endif()
......
......@@ -170,12 +170,12 @@ class MethodName(Name):
def to_c(self):
suffix = ('_' + str(self.overloadRef)) if self.overloadRef > 0 else ''
return Name.to_snake_case(self, fullName=True) + suffix
return self.to_snake_case(fullName=True) + suffix
class ArgName(Name):
def to_c(self):
return Name.to_snake_case(self)
return self.to_snake_case()
class PropertyName(ArgName):
......@@ -478,16 +478,16 @@ class CParser(object):
def parse_all(self):
for enum in self.cProject.enums:
CParser.parse_enum(self, enum)
self.parse_enum(enum)
for _class in self.cProject.classes:
try:
CParser.parse_class(self, _class)
self.parse_class(_class)
except BlacklistedException:
pass
except Error as e:
print('Could not parse \'{0}\' class: {1}'.format(_class.name, e.args[0]))
CParser._fix_all_types(self)
self._fix_all_types()
def _class_is_refcountable(self, _class):
......@@ -499,33 +499,38 @@ class CParser(object):
return True
return False
def _fix_all_types_in_class_or_interface(self, _class):
if _class is not None:
if type(_class) is Class:
self._fix_all_types_in_class(_class)
else:
self._fix_all_types_in_interface(_class)
def _fix_all_types(self):
for _class in self.classesIndex.values() + self.interfacesIndex.values():
if _class is not None:
if type(_class) is Class:
CParser._fix_all_types_in_class(self, _class)
else:
CParser._fix_all_types_in_interface(self, _class)
for _class in self.interfacesIndex.values():
self._fix_all_types_in_class_or_interface(_class)
for _class in self.classesIndex.values():
self._fix_all_types_in_class_or_interface(_class)
def _fix_all_types_in_class(self, _class):
for property in _class.properties:
if property.setter is not None:
CParser._fix_all_types_in_method(self, property.setter)
self._fix_all_types_in_method(property.setter)
if property.getter is not None:
CParser._fix_all_types_in_method(self, property.getter)
self._fix_all_types_in_method(property.getter)
for method in (_class.instanceMethods + _class.classMethods):
CParser._fix_all_types_in_method(self, method)
self._fix_all_types_in_method(method)
def _fix_all_types_in_interface(self, interface):
for method in interface.methods:
CParser._fix_all_types_in_method(self, method)
self._fix_all_types_in_method(method)
def _fix_all_types_in_method(self, method):
try:
CParser._fix_type(self, method.returnType)
self._fix_type(method.returnType)
for arg in method.args:
CParser._fix_type(self, arg.type)
self._fix_type(arg.type)
except Error as e:
print('warning: some types could not be fixed in {0}() function: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0]))
......@@ -546,7 +551,7 @@ class CParser(object):
_type.containedTypeDesc = EnumType(_type.containedTypeName, enumDesc=self.enumsIndex[_type.containedTypeName])
else:
if _type.containedTypeName is not None:
_type.containedTypeDesc = CParser.parse_c_base_type(self, _type.containedTypeName)
_type.containedTypeDesc = self.parse_c_base_type(_type.containedTypeName)
else:
raise Error('bctbx_list_t type without specified contained type')
......@@ -575,10 +580,10 @@ class CParser(object):
raise BlacklistedException('{0} is blacklisted'.format(cclass.name));
if cclass.name.endswith('Cbs'):
_class = CParser._parse_listener(self, cclass)
_class = self._parse_listener(cclass)
self.interfacesIndex[cclass.name] = _class
else:
_class = CParser._parse_class(self, cclass)
_class = self._parse_class(cclass)
self.classesIndex[cclass.name] = _class
self.namespace.add_child(_class)
return _class
......@@ -587,12 +592,12 @@ class CParser(object):
name = ClassName()
name.from_camel_case(cclass.name, namespace=self.namespace.name)
_class = Class(name)
_class.refcountable = CParser._class_is_refcountable(self, cclass)
_class.refcountable = self._class_is_refcountable(cclass)
for cproperty in cclass.properties.values():
try:
if cproperty.name != 'callbacks':
absProperty = CParser._parse_property(self, cproperty, namespace=name)
absProperty = self._parse_property(cproperty, namespace=name)
_class.add_property(absProperty)
else:
_class.listenerInterface = self.interfacesIndex[cproperty.getter.returnArgument.ctype]
......@@ -601,7 +606,7 @@ class CParser(object):
for cMethod in cclass.instanceMethods.values():
try:
method = CParser.parse_method(self, cMethod, namespace=name)
method = self.parse_method(cMethod, namespace=name)
if method.name.to_snake_case() == 'add_callbacks' or method.name.to_snake_case() == 'remove_callbacks':
if _class.listenerInterface is None or not _class.multilistener:
_class.multilistener = True
......@@ -618,7 +623,7 @@ class CParser(object):
for cMethod in cclass.classMethods.values():
try:
method = CParser.parse_method(self, cMethod, type=Method.Type.Class, namespace=name)
method = self.parse_method(cMethod, type=Method.Type.Class, namespace=name)
_class.add_class_method(method)
except BlacklistedException:
pass
......@@ -636,10 +641,10 @@ class CParser(object):
methodType = Method.Type.Instance
aproperty = Property(name)
if cproperty.setter is not None:
method = CParser.parse_method(self, cproperty.setter, namespace=namespace, type=methodType)
method = self.parse_method(cproperty.setter, namespace=namespace, type=methodType)
aproperty.setter = method
if cproperty.getter is not None:
method = CParser.parse_method(self, cproperty.getter, namespace=namespace, type=methodType)
method = self.parse_method(cproperty.getter, namespace=namespace, type=methodType)
aproperty.getter = method
return aproperty
......@@ -658,7 +663,7 @@ class CParser(object):
for property in cclass.properties.values():
if property.name != 'user_data':
try:
method = CParser._parse_listener_property(self, property, listener, cclass.events)
method = self._parse_listener_property(property, listener, cclass.events)
listener.add_method(method)
except Error as e:
print('Could not parse property \'{0}\' of listener \'{1}\': {2}'.format(property.name, cclass.name, e.args[0]))
......@@ -684,11 +689,11 @@ class CParser(object):
raise Error('invalid event name \'{0}\''.format(eventName))
method = Method(methodName)
method.returnType = CParser.parse_type(self, event.returnArgument)
method.returnType = self.parse_type(event.returnArgument)
for arg in event.arguments:
argName = ArgName()
argName.from_snake_case(arg.name)
argument = Argument(argName, CParser.parse_type(self, arg))
argument = Argument(argName, self.parse_type(arg))
method.add_arguments(argument)
return method
......@@ -697,18 +702,18 @@ class CParser(object):
name = MethodName()
name.from_snake_case(cfunction.name, namespace=namespace)
if CParser._is_blacklisted(self, name):
if self._is_blacklisted(name):
raise BlacklistedException('{0} is blacklisted'.format(name.to_c()));
method = Method(name, type=type)
method.deprecated = cfunction.deprecated
method.returnType = CParser.parse_type(self, cfunction.returnArgument)
method.returnType = self.parse_type(cfunction.returnArgument)
for arg in cfunction.arguments:
if type == Method.Type.Instance and arg is cfunction.arguments[0]:
method.constMethod = ('const' in arg.completeType.split(' '))
else:
aType = CParser.parse_type(self, arg)
aType = self.parse_type(arg)
argName = ArgName()
argName.from_snake_case(arg.name)
absArg = Argument(argName, aType)
......@@ -718,7 +723,7 @@ class CParser(object):
def parse_type(self, cType):
if cType.ctype in self.cBaseType or re.match(self.regexFixedSizeInteger, cType.ctype):
absType = CParser.parse_c_base_type(self, cType.completeType)
absType = self.parse_c_base_type(cType.completeType)
elif cType.ctype in self.enumsIndex:
absType = EnumType(cType.ctype, enumDesc=self.enumsIndex[cType.ctype])
elif cType.ctype in self.classesIndex or cType.ctype in self.interfacesIndex:
......
......@@ -36,7 +36,7 @@ class CppTranslator(object):
self.ambigousTypes = ['LinphonePayloadType']
def is_ambigous_type(self, _type):
return _type.name in self.ambigousTypes or (_type.name == 'list' and CppTranslator.is_ambigous_type(self, _type.containedTypeDesc))
return _type.name in self.ambigousTypes or (_type.name == 'list' and self.is_ambigous_type(_type.containedTypeDesc))
@staticmethod
def translate_enum(enum):
......@@ -92,7 +92,7 @@ class CppTranslator(object):
classDict['cListenerName'] = _class.listenerInterface.name.to_c()
classDict['cppListenerName'] = CppTranslator.translate_class_name(_class.listenerInterface.name)
for method in _class.listenerInterface.methods:
classDict['wrapperCbs'].append(CppTranslator._generate_wrapper_callback(self, _class, method))
classDict['wrapperCbs'].append(self._generate_wrapper_callback(_class, method))
if ismonolistenable:
classDict['cCbsGetter'] = _class.name.to_snake_case(fullName=True) + '_get_callbacks'
......@@ -106,22 +106,22 @@ class CppTranslator(object):
classDict['userDataGetter'] = _class.listenerInterface.name.to_snake_case(fullName=True)[:-len('_listener')] + '_cbs_get_user_data'
classDict['currentCallbacksGetter'] = _class.name.to_snake_case(fullName=True) + '_get_current_callbacks'
for property in _class.properties:
for _property in _class.properties:
try:
classDict['methods'] += CppTranslator.translate_property(self, property)
classDict['methods'] += self.translate_property(_property)
except AbsApi.Error as e:
print('error while translating {0} property: {1}'.format(property.name.to_snake_case(), e.args[0]))
print('error while translating {0} property: {1}'.format(_property.name.to_snake_case(), e.args[0]))
for method in _class.instanceMethods:
try:
methodDict = CppTranslator.translate_method(self, method)
methodDict = self.translate_method(method)
classDict['methods'].append(methodDict)
except AbsApi.Error as e:
print('Could not translate {0}: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0]))
for method in _class.classMethods:
try:
methodDict = CppTranslator.translate_method(self, method)
methodDict = self.translate_method(method)
classDict['staticMethods'].append(methodDict)
except AbsApi.Error as e:
print('Could not translate {0}: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0]))
......@@ -138,7 +138,7 @@ class CppTranslator(object):
wrappedArgs = []
for arg in method.args:
args.append(arg.type.cname + ' ' + arg.name.to_c())
wrappedArgs.append(CppTranslator._wrap_c_expression_to_cpp(self, arg.name.to_c(), arg.type, usedNamespace=namespace))
wrappedArgs.append(self._wrap_c_expression_to_cpp(arg.name.to_c(), arg.type, usedNamespace=namespace))
params['params'] = ', '.join(args)
params['returnType'] = method.returnType.cname
......@@ -153,9 +153,7 @@ class CppTranslator(object):
wrapperCbDict['cppMethodCallingLine'] = 'listener->{methodName}({wrappedArgs})'.format(
methodName=method.name.to_camel_case(lower=True),
wrappedArgs=', '.join(wrappedArgs))
wrapperCbDict['cppMethodCallingLine'] = CppTranslator._wrap_cpp_expression_to_c(self,
wrapperCbDict['cppMethodCallingLine'],
method.returnType)
wrapperCbDict['cppMethodCallingLine'] = self._wrap_cpp_expression_to_c(wrapperCbDict['cppMethodCallingLine'], method.returnType)
return wrapperCbDict
def translate_interface(self, interface):
......@@ -171,19 +169,19 @@ class CppTranslator(object):
intDict['methods'] = []
for method in interface.methods:
try:
methodDict = CppTranslator.translate_method(self, method, genImpl=False)
methodDict = self.translate_method(method, genImpl=False)
intDict['methods'].append(methodDict)
except AbsApi.Error as e:
print('Could not translate {0}: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0]))
return intDict
def translate_property(self, property):
def translate_property(self, _property):
res = []
if property.getter is not None:
res.append(CppTranslator.translate_method(self, property.getter))
if property.setter is not None:
res.append(CppTranslator.translate_method(self, property.setter))
if _property.getter is not None:
res.append(self.translate_method(_property.getter))
if _property.setter is not None:
res.append(self.translate_method(_property.setter))
return res
def translate_method(self, method, genImpl=True):
......@@ -193,14 +191,14 @@ class CppTranslator(object):
namespace = method.find_first_ancestor_by_type(AbsApi.Namespace)
methodElems = {}
methodElems['return'] = CppTranslator.translate_type(self, method.returnType)
methodElems['return'] = self.translate_type(method.returnType)
methodElems['name'] = CppTranslator.translate_method_name(method.name)
methodElems['params'] = ''
for arg in method.args:
if arg is not method.args[0]:
methodElems['params'] += ', '
methodElems['params'] += CppTranslator.translate_argument(self, arg)
methodElems['params'] += self.translate_argument(arg)
methodElems['const'] = ' const' if method.constMethod else ''
methodElems['semicolon'] = ';'
......@@ -221,20 +219,20 @@ class CppTranslator(object):
methodDict['prototype'] = 'LINPHONECXX_PUBLIC {deprecated}{methodType}{return} {name}({params}){const}{semicolon}'.format(**methodElems)
if genImpl:
if not CppTranslator.is_ambigous_type(self, method.returnType):
methodElems['implReturn'] = CppTranslator.translate_type(self, method.returnType, namespace=namespace)
if not self.is_ambigous_type(method.returnType):
methodElems['implReturn'] = self.translate_type(method.returnType, namespace=namespace)
else:
methodElems['implReturn'] = CppTranslator.translate_type(self, method.returnType, namespace=None)
methodElems['implReturn'] = self.translate_type(method.returnType, namespace=None)
methodElems['longname'] = CppTranslator.translate_method_name(method.name, recursive=True)
methodElems['implParams'] = ''
for arg in method.args:
if arg is not method.args[0]:
methodElems['implParams'] += ', '
methodElems['implParams'] += CppTranslator.translate_argument(self, arg, namespace=namespace)
methodElems['implParams'] += self.translate_argument(arg, namespace=namespace)
methodDict['implPrototype'] = '{implReturn} {longname}({implParams}){const}'.format(**methodElems)
methodDict['sourceCode' ] = CppTranslator._generate_source_code(self, method, usedNamespace=namespace)
methodDict['sourceCode' ] = self._generate_source_code(method, usedNamespace=namespace)
return methodDict
......@@ -242,12 +240,12 @@ class CppTranslator(object):
nsName = usedNamespace.name if usedNamespace is not None else None
params = {
'functionName': method.name.to_c(),
'args': CppTranslator._generate_wrapped_arguments(self, method, usedNamespace=usedNamespace)
'args': self._generate_wrapped_arguments(method, usedNamespace=usedNamespace)
}
if method.name.to_camel_case(lower=True) != 'setListener':
cExpr = '{functionName}({args})'.format(**params)
cppExpr = CppTranslator._wrap_c_expression_to_cpp(self, cExpr, method.returnType, usedNamespace=usedNamespace)
cppExpr = self._wrap_c_expression_to_cpp(cExpr, method.returnType, usedNamespace=usedNamespace)
else:
cppExpr = 'ListenableObject::setListener(std::static_pointer_cast<Listener>({0}))'.format(method.args[0].name.to_snake_case())
......@@ -265,7 +263,7 @@ class CppTranslator(object):
for arg in method.args:
paramName = arg.name.to_camel_case(lower=True)
args.append(CppTranslator._wrap_cpp_expression_to_c(self, paramName, arg.type, usedNamespace=usedNamespace))
args.append(self._wrap_cpp_expression_to_c(paramName, arg.type, usedNamespace=usedNamespace))
return ', '.join(args)
......@@ -280,7 +278,7 @@ class CppTranslator(object):
elif type(exprtype) is AbsApi.ClassType:
cPtrType = exprtype.desc.name.to_c()
if exprtype.desc.refcountable:
ptrType = CppTranslator.translate_class_type(self, exprtype, namespace=usedNamespace)
ptrType = self.translate_class_type(exprtype, namespace=usedNamespace)
ptrType = CppTranslator.sharedPtrTypeExtractor.match(ptrType).group(2)
param = {
'ptrType' : ptrType,
......@@ -298,7 +296,7 @@ class CppTranslator(object):
if type(exprtype.containedTypeDesc) is AbsApi.BaseType and exprtype.containedTypeDesc.name == 'string':
cExpr = 'StringBctbxListWrapper({0}).c_list()'.format(cppExpr)
elif type(exprtype.containedTypeDesc) is AbsApi.ClassType:
ptrType = CppTranslator.translate_class_type(self, exprtype.containedTypeDesc, namespace=usedNamespace)
ptrType = self.translate_class_type(exprtype.containedTypeDesc, namespace=usedNamespace)
if exprtype.containedTypeDesc.desc.refcountable:
ptrType = CppTranslator.sharedPtrTypeExtractor.match(ptrType).group(2)
cExpr = 'ObjectBctbxListWrapper<{0}>({1}).c_list()'.format(ptrType, cppExpr)
......@@ -324,10 +322,10 @@ class CppTranslator(object):
else:
return cExpr
elif type(exprtype) is AbsApi.EnumType:
cppEnumName = CppTranslator.translate_enum_type(self, exprtype, namespace=usedNamespace)
cppEnumName = self.translate_enum_type(exprtype, namespace=usedNamespace)
return '({0}){1}'.format(cppEnumName, cExpr)
elif type(exprtype) is AbsApi.ClassType:
cppReturnType = CppTranslator.translate_class_type(self, exprtype, namespace=usedNamespace)
cppReturnType = self.translate_class_type(exprtype, namespace=usedNamespace)
if exprtype.desc.refcountable:
cppReturnType = CppTranslator.sharedPtrTypeExtractor.match(cppReturnType).group(2)
......@@ -347,7 +345,7 @@ class CppTranslator(object):
if type(exprtype.containedTypeDesc) is AbsApi.BaseType and exprtype.containedTypeDesc.name == 'string':
return 'StringBctbxListWrapper::bctbxListToCppList({0})'.format(cExpr)
elif type(exprtype.containedTypeDesc) is AbsApi.ClassType:
cppReturnType = CppTranslator.translate_class_type(self, exprtype.containedTypeDesc, namespace=usedNamespace)
cppReturnType = self.translate_class_type(exprtype.containedTypeDesc, namespace=usedNamespace)
if exprtype.containedTypeDesc.desc.refcountable:
cppReturnType = CppTranslator.sharedPtrTypeExtractor.match(cppReturnType).group(2)
return 'ObjectBctbxListWrapper<{0}>::bctbxListToCppList({1})'.format(cppReturnType, cExpr)
......@@ -360,17 +358,17 @@ class CppTranslator(object):
return cExpr
def translate_argument(self, arg, **params):
return '{0} {1}'.format(CppTranslator.translate_type(self, arg.type, **params), CppTranslator.translate_argument_name(arg.name))
return '{0} {1}'.format(self.translate_type(arg.type, **params), CppTranslator.translate_argument_name(arg.name))
def translate_type(self, aType, **params):
if type(aType) is AbsApi.BaseType:
return CppTranslator.translate_base_type(self, aType)
return self.translate_base_type(aType)
elif type(aType) is AbsApi.EnumType:
return CppTranslator.translate_enum_type(self, aType, **params)
return self.translate_enum_type(aType, **params)
elif type(aType) is AbsApi.ClassType:
return CppTranslator.translate_class_type(self, aType, **params)
return self.translate_class_type(aType, **params)
elif type(aType) is AbsApi.ListType:
return CppTranslator.translate_list_type(self, aType, **params)
return self.translate_list_type(aType, **params)
else:
CppTranslator.fail(aType)
......@@ -473,9 +471,9 @@ class CppTranslator(object):
if _type.containedTypeDesc is None:
raise AbsApi.Error('{0} has not been fixed'.format(_type.containedTypeName))
elif isinstance(_type.containedTypeDesc, AbsApi.BaseType):
res = CppTranslator.translate_type(self, _type.containedTypeDesc)
res = self.translate_type(_type.containedTypeDesc)
else:
res = CppTranslator.translate_type(self, _type.containedTypeDesc, **params)
res = self.translate_type(_type.containedTypeDesc, **params)
if type(_type.parent) is AbsApi.Argument:
return 'const std::list<{0} > &'.format(res)
......@@ -576,7 +574,7 @@ class ClassHeader(object):
self.private_type = _class.name.to_camel_case(fullName=True)
self.includes = {'internal': [], 'external': []}
includes = ClassHeader.needed_includes(self, _class)
includes = self.needed_includes(_class)
for include in includes['internal']:
if _class.name.to_camel_case(fullName=True) == 'LinphoneCore' or (isinstance(_class, AbsApi.Interface) and _class.listenedClass is not None and include == _class.listenedClass.name.to_snake_case()):
if include == 'enums':
......@@ -592,16 +590,16 @@ class ClassHeader(object):
self.includes['external'].append({'name': include})
def needed_includes(self, _class):
includes = {'internal': set(), 'external': set()}
includes = {'internal': [], 'external': []}
if type(_class) is AbsApi.Class:
includes['internal'].add('object')
self._add_include(includes, 'internal', 'object')
for property in _class.properties:
if property.setter is not None:
ClassHeader._needed_includes_from_method(self, property.setter, includes)
if property.getter is not None:
ClassHeader._needed_includes_from_method(self, property.getter, includes)
for _property in _class.properties:
if _property.setter is not None:
self._needed_includes_from_method(_property.setter, includes)
if _property.getter is not None:
self._needed_includes_from_method(_property.getter, includes)
if type(_class) is AbsApi.Class:
methods = _class.classMethods + _class.instanceMethods
......@@ -609,12 +607,12 @@ class ClassHeader(object):
methods = _class.methods
for method in methods:
ClassHeader._needed_includes_from_type(self, method.returnType, includes)
self._needed_includes_from_type(method.returnType, includes)
for arg in method.args:
ClassHeader._needed_includes_from_type(self, arg.type, includes)
self._needed_includes_from_type(arg.type, includes)
if isinstance(_class, AbsApi.Class) and _class.listenerInterface is not None:
includes['internal'].add(_class.listenerInterface.name.to_snake_case())
self._add_include(includes, 'internal', _class.listenerInterface.name.to_snake_case())
currentClassInclude = _class.name.to_snake_case()
if currentClassInclude in includes['internal']:
......@@ -623,25 +621,29 @@ class ClassHeader(object):
return includes
def _needed_includes_from_method(self, method, includes):
ClassHeader._needed_includes_from_type(self, method.returnType, includes)
self._needed_includes_from_type(method.returnType, includes)
for arg in method.args:
ClassHeader._needed_includes_from_type(self, arg.type, includes)
self._needed_includes_from_type(arg.type, includes)
def _needed_includes_from_type(self, _type, includes):
if isinstance(_type, AbsApi.ClassType):
includes['external'].add('memory')
self._add_include(includes, 'external', 'memory')
if _type.desc is not None:
includes['internal'].add(_type.desc.name.to_snake_case())
self._add_include(includes, 'internal', _type.desc.name.to_snake_case())
elif isinstance(_type, AbsApi.EnumType):
includes['internal'].add('enums')
self._add_include(includes, 'internal', 'enums')
elif isinstance(_type, AbsApi.BaseType):
if _type.name == 'integer' and isinstance(_type.size, int):
includes['external'].add('cstdint')
self._add_include(includes, 'external', 'cstdint')
elif _type.name == 'string':
includes['external'].add('string')
self._add_include(includes, 'external', 'string')
elif isinstance(_type, AbsApi.ListType):
includes['external'].add('list')
ClassHeader._needed_includes_from_type(self, _type.containedTypeDesc, includes)
self._add_include(includes, 'external', 'list')
self._needed_includes_from_type(_type.containedTypeDesc, includes)
def _add_include(self, includes, location, name):
if not name in includes[location]:
includes[location].append(name)
class MainHeader(object):
......@@ -658,16 +660,65 @@ class ClassImpl(object):
self.classes = []
self.namespace = 'linphone'
def render(renderer, item, path):
tmppath = path + '.tmp'
content = ''
with open(tmppath, mode='w') as f:
f.write(renderer.render(item))
with open(tmppath, mode='rU') as f:
content = f.read()
with open(path, mode='w') as f:
f.write(content)
os.unlink(tmppath)
class GenWrapper(object):
def __init__(self, includedir, srcdir, xmldir):
self.includedir = includedir
self.srcdir = srcdir
project = CApi.Project()
project.initFromDir(xmldir)
project.check()
self.parser = AbsApi.CParser(project)
self.parser.parse_all()
self.translator = CppTranslator()
self.renderer = pystache.Renderer()
self.mainHeader = MainHeader()
self.impl = ClassImpl()
def render_all(self):
header = EnumsHeader(self.translator)
for item in self.parser.enumsIndex.items():
if item[1] is not None:
header.add_enum(item[1])
else:
print('warning: {0} enum won\'t be translated because of parsing errors'.format(item[0]))
self.render(header, self.includedir + '/enums.hh')
self.mainHeader.add_include('enums.hh')
for _class in self.parser.interfacesIndex.values():
self.render_header(_class)
for _class in self.parser.classesIndex.values():
self.render_header(_class)
self.render(self.mainHeader, self.includedir + '/linphone.hh')
self.render(self.impl, self.srcdir + '/linphone++.cc')
def render(self, item, path):
tmppath = path + '.tmp'
content = ''
with open(tmppath, mode='w') as f:
f.write(self.renderer.render(item))
with open(tmppath, mode='rU') as f:
content = f.read()
with open(path, mode='w') as f:
f.write(content)
os.unlink(tmppath)
def render_header(self, _class):
if _class is not None: