forked from mirrors/linphone-iphone
This reverts commit 7d621c5bd1 and
proposes a way to fix the generation with Python 2 without
breaking abstractapi's interface.
541 lines
21 KiB
Python
Executable file
541 lines
21 KiB
Python
Executable file
#!/usr/bin/python
|
|
|
|
# Copyright (C) 2017 Belledonne Communications SARL
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License
|
|
# as published by the Free Software Foundation; either version 2
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
import pystache
|
|
import re
|
|
import argparse
|
|
import os
|
|
import os.path
|
|
import sys
|
|
import errno
|
|
import logging
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'tools'))
|
|
import genapixml as CApi
|
|
import abstractapi as AbsApi
|
|
import metadoc
|
|
import metaname
|
|
|
|
|
|
class CppTranslator(object):
|
|
sharedPtrTypeExtractor = re.compile('^(const )?std::shared_ptr<(.+)>( &)?$')
|
|
|
|
def __init__(self, rootNs=None):
|
|
self.nameTranslator = metaname.Translator.get('Cpp')
|
|
self.langTranslator = AbsApi.Translator.get('Cpp')
|
|
self.langTranslator.ambigousTypes.append('LinphonePayloadType')
|
|
self.docTranslator = metadoc.DoxygenTranslator('Cpp')
|
|
self.rootNs = rootNs
|
|
|
|
def translate_enum(self, enum):
|
|
enumDict = {}
|
|
enumDict['name'] = enum.name.translate(self.nameTranslator)
|
|
enumDict['doc'] = enum.briefDescription.translate(self.docTranslator)
|
|
enumDict['enumerators'] = []
|
|
for enumerator in enum.enumerators:
|
|
enumeratorDict = self.translate_enumerator(enumerator)
|
|
enumeratorDict['notLast'] = (enumerator is not enum.enumerators[-1])
|
|
enumDict['enumerators'].append(enumeratorDict)
|
|
return enumDict
|
|
|
|
def translate_enumerator(self, enumerator):
|
|
enumeratorDict = {
|
|
'name' : enumerator.name.translate(self.nameTranslator),
|
|
'value' : enumerator.translate_value(self.langTranslator)
|
|
}
|
|
try:
|
|
enumeratorDict['doc'] = enumerator.briefDescription.translate(self.docTranslator)
|
|
except metadoc.TranslationError as e:
|
|
logging.error(e.msg())
|
|
return enumeratorDict
|
|
|
|
def translate_class(self, _class):
|
|
islistenable = _class.listenerInterface is not None
|
|
ismonolistenable = (islistenable and not _class.multilistener)
|
|
ismultilistenable = (islistenable and _class.multilistener)
|
|
|
|
classDict = {
|
|
'islistenable' : islistenable,
|
|
'isnotlistenable' : not islistenable,
|
|
'ismonolistenable' : ismonolistenable,
|
|
'ismultilistenable' : ismultilistenable,
|
|
'isrefcountable' : _class.refcountable,
|
|
'isnotrefcountable' : not _class.refcountable,
|
|
'isNotListener' : True,
|
|
'isListener' : False,
|
|
'isVcard' : (_class.name.to_c() == 'LinphoneVcard'),
|
|
'className' : _class.name.translate(self.nameTranslator),
|
|
'cClassName' : '::' + _class.name.to_c(),
|
|
'privCClassName' : '_' + _class.name.to_c(),
|
|
'parentClassName' : 'Object' if _class.refcountable else None,
|
|
'enums' : [],
|
|
'methods' : [],
|
|
'staticMethods' : [],
|
|
'wrapperCbs' : [],
|
|
'friendClasses' : []
|
|
}
|
|
|
|
if _class.name.to_c() == 'LinphoneCore':
|
|
classDict['friendClasses'].append({'name': 'Factory'});
|
|
|
|
try:
|
|
classDict['briefDoc'] = _class.briefDescription.translate(self.docTranslator, tagAsBrief=True)
|
|
classDict['detailedDoc'] = _class.detailedDescription.translate(self.docTranslator)
|
|
except metadoc.TranslationError as e:
|
|
logging.error(e.msg())
|
|
|
|
if islistenable:
|
|
classDict['listenerClassName'] = _class.listenerInterface.name.translate(self.nameTranslator)
|
|
classDict['cListenerName'] = _class.listenerInterface.name.to_c()
|
|
classDict['cppListenerName'] = _class.listenerInterface.name.translate(self.nameTranslator)
|
|
for method in _class.listenerInterface.methods:
|
|
classDict['wrapperCbs'].append(self._generate_wrapper_callback(_class, method))
|
|
|
|
if ismonolistenable:
|
|
classDict['cCbsGetter'] = _class.name.to_snake_case(fullName=True) + '_get_callbacks'
|
|
classDict['parentClassName'] = 'ListenableObject'
|
|
elif ismultilistenable:
|
|
classDict['parentClassName'] = 'MultiListenableObject'
|
|
classDict['listenerCreator'] = 'linphone_factory_create_' + _class.listenerInterface.name.to_snake_case()[:-len('_listener')] + '_cbs'
|
|
classDict['callbacksAdder'] = _class.name.to_snake_case(fullName=True)+ '_add_callbacks'
|
|
classDict['callbacksRemover'] = _class.name.to_snake_case(fullName=True)+ '_remove_callbacks'
|
|
classDict['userDataSetter'] = _class.listenerInterface.name.to_snake_case(fullName=True)[:-len('_listener')] + '_cbs_set_user_data'
|
|
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 enum in _class.enums:
|
|
classDict['enums'].append(self.translate_enum(enum))
|
|
|
|
for _property in _class.properties:
|
|
classDict['methods'] += self.translate_property(_property)
|
|
|
|
for method in _class.instanceMethods:
|
|
methodDict = self.translate_method(method)
|
|
classDict['methods'].append(methodDict)
|
|
|
|
for method in _class.classMethods:
|
|
methodDict = self.translate_method(method)
|
|
classDict['staticMethods'].append(methodDict)
|
|
|
|
return classDict
|
|
|
|
def _generate_wrapper_callback(self, listenedClass, method):
|
|
namespace = method.find_first_ancestor_by_type(AbsApi.Namespace)
|
|
listenedClass = method.find_first_ancestor_by_type(AbsApi.Interface).listenedClass
|
|
|
|
params = {}
|
|
params['name'] = method.name.to_snake_case(fullName=True) + '_cb'
|
|
args = []
|
|
wrappedArgs = []
|
|
for arg in method.args:
|
|
args.append(arg.type.cDecl + ' ' + arg.name.to_c())
|
|
wrappedArgs.append(self._wrap_c_expression_to_cpp(arg.name.to_c(), arg.type, usedNamespace=namespace))
|
|
params['params'] = ', '.join(args)
|
|
params['returnType'] = method.returnType.cDecl
|
|
|
|
wrapperCbDict = {}
|
|
wrapperCbDict['cbName'] = params['name']
|
|
wrapperCbDict['declArgs'] = params['params']
|
|
wrapperCbDict['firstArgName'] = method.args[0].name.to_c()
|
|
wrapperCbDict['returnType'] = params['returnType']
|
|
wrapperCbDict['hasReturnValue'] = (params['returnType'] != 'void')
|
|
wrapperCbDict['hasNotReturnValue'] = not wrapperCbDict['hasReturnValue']
|
|
wrapperCbDict['callbackSetter'] = listenedClass.name.to_snake_case(fullName=True) + '_cbs_set_' + method.name.to_snake_case()[3:]
|
|
wrapperCbDict['cppMethodCallingLine'] = 'listener->{methodName}({wrappedArgs})'.format(
|
|
methodName=method.name.to_camel_case(lower=True),
|
|
wrappedArgs=', '.join(wrappedArgs))
|
|
wrapperCbDict['cppMethodCallingLine'] = self._wrap_cpp_expression_to_c(wrapperCbDict['cppMethodCallingLine'], method.returnType)
|
|
return wrapperCbDict
|
|
|
|
def translate_interface(self, interface):
|
|
intDict = {
|
|
'inheritFrom' : {'name': 'Listener'},
|
|
'className' : interface.name.translate(self.nameTranslator),
|
|
'constructor' : None,
|
|
'parentClassName' : 'Listener',
|
|
'isNotListener' : False,
|
|
'isListener' : True,
|
|
'methods' : []
|
|
}
|
|
for method in interface.methods:
|
|
methodDict = self.translate_method(method, genImpl=False)
|
|
intDict['methods'].append(methodDict)
|
|
|
|
return intDict
|
|
|
|
def translate_property(self, _property):
|
|
res = []
|
|
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):
|
|
namespace = method.find_first_ancestor_by_type(AbsApi.Class, AbsApi.Interface)
|
|
|
|
methodDict = {
|
|
'declPrototype': method.translate_as_prototype(self.langTranslator, namespace=namespace),
|
|
'implPrototype': method.translate_as_prototype(self.langTranslator, namespace=AbsApi.GlobalNs),
|
|
'deprecated': method.deprecated,
|
|
'suffix': '',
|
|
}
|
|
|
|
try:
|
|
methodDict['briefDoc'] = method.briefDescription.translate(self.docTranslator, tagAsBrief=True) if method.briefDescription is not None else None
|
|
methodDict['detailedDoc'] = method.detailedDescription.translate(self.docTranslator) if method.detailedDescription is not None else None
|
|
except metadoc.TranslationError as e:
|
|
logging.error(e.msg())
|
|
|
|
if type(method.parent) is AbsApi.Interface:
|
|
if isinstance(method.returnType, AbsApi.BaseType) and method.returnType.name == 'void':
|
|
methodDict['suffix'] = ' {}'
|
|
else:
|
|
methodDict['suffix'] = ' = 0'
|
|
|
|
if genImpl:
|
|
methodDict['sourceCode' ] = self._generate_source_code(method, usedNamespace=namespace)
|
|
|
|
return methodDict
|
|
|
|
def _generate_source_code(self, method, usedNamespace=None):
|
|
nsName = usedNamespace.name if usedNamespace is not None else None
|
|
params = {
|
|
'functionName': method.name.to_c(),
|
|
'args': self._generate_wrapped_arguments(method, usedNamespace=usedNamespace)
|
|
}
|
|
|
|
if method.name.to_camel_case(lower=True) != 'setListener':
|
|
cExpr = '{functionName}({args})'.format(**params)
|
|
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())
|
|
|
|
if type(method.returnType) is AbsApi.BaseType and method.returnType.name == 'void' and not method.returnType.isref:
|
|
return cppExpr + ';'
|
|
else:
|
|
return 'return {0};'.format(cppExpr)
|
|
|
|
def _generate_wrapped_arguments(self, method, usedNamespace=None):
|
|
args = []
|
|
if method.type == AbsApi.Method.Type.Instance:
|
|
_class = method.find_first_ancestor_by_type(AbsApi.Class)
|
|
argStr = '(::{0} *)mPrivPtr'.format(_class.name.to_camel_case(fullName=True))
|
|
args.append(argStr)
|
|
|
|
for arg in method.args:
|
|
paramName = arg.name.to_camel_case(lower=True)
|
|
args.append(self._wrap_cpp_expression_to_c(paramName, arg.type, usedNamespace=usedNamespace))
|
|
|
|
return ', '.join(args)
|
|
|
|
def _wrap_cpp_expression_to_c(self, cppExpr, exprtype, usedNamespace=None):
|
|
if type(exprtype) is AbsApi.BaseType:
|
|
if exprtype.name == 'string':
|
|
cExpr = 'StringUtilities::cppStringToC({0})'.format(cppExpr);
|
|
else:
|
|
cExpr = cppExpr
|
|
elif type(exprtype) is AbsApi.EnumType:
|
|
cExpr = '(::{0}){1}'.format(exprtype.desc.name.to_c(), cppExpr)
|
|
elif type(exprtype) is AbsApi.ClassType:
|
|
cPtrType = exprtype.desc.name.to_c()
|
|
if exprtype.desc.refcountable:
|
|
ptrType = exprtype.translate(self.langTranslator, namespace=usedNamespace)
|
|
ptrType = CppTranslator.sharedPtrTypeExtractor.match(ptrType).group(2)
|
|
param = {
|
|
'ptrType' : ptrType,
|
|
'cPtrType': cPtrType,
|
|
'cppExpr' : cppExpr,
|
|
'object' : 'const Object' if exprtype.isconst else 'Object'
|
|
}
|
|
cExpr = '(::{cPtrType} *)Object::sharedPtrToCPtr(std::static_pointer_cast<{object},{ptrType}>({cppExpr}))'.format(**param)
|
|
else:
|
|
if exprtype.isref:
|
|
cExpr = '(const ::{_type} *)({expr}).c_struct()'.format(_type=cPtrType, expr=cppExpr)
|
|
else:
|
|
cExpr = '*(const ::{_type} *)({expr}).c_struct()'.format(_type=cPtrType, expr=cppExpr)
|
|
elif type(exprtype) is AbsApi.ListType:
|
|
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 = exprtype.containedTypeDesc.translate(self.langTranslator, namespace=usedNamespace)
|
|
if exprtype.containedTypeDesc.desc.refcountable:
|
|
ptrType = CppTranslator.sharedPtrTypeExtractor.match(ptrType).group(2)
|
|
cExpr = 'ObjectBctbxListWrapper<{0}>({1}).c_list()'.format(ptrType, cppExpr)
|
|
else:
|
|
cType = exprtype.containedTypeDesc.desc.name.to_c()
|
|
if exprtype.isconst:
|
|
cExpr = 'StructBctbxListWrapper<{0},{1}>({2}).c_list()'.format(ptrType, cType, cppExpr)
|
|
else:
|
|
cExpr = 'StructBctbxListWrapper<{0},{1}>::cppListToBctbxList({2})'.format(ptrType, cType, cppExpr)
|
|
else:
|
|
raise AbsApi.Error('translation of bctbx_list_t of enums or basic C types is not supported')
|
|
|
|
return cExpr
|
|
|
|
def _wrap_c_expression_to_cpp(self, cExpr, exprtype, usedNamespace=None):
|
|
if type(exprtype) is AbsApi.BaseType:
|
|
if exprtype.name == 'string':
|
|
return 'StringUtilities::cStringToCpp({0})'.format(cExpr)
|
|
elif exprtype.name == 'string_array':
|
|
return 'StringUtilities::cStringArrayToCppList({0})'.format(cExpr)
|
|
elif exprtype.name == 'boolean':
|
|
return '({0} != FALSE)'.format(cExpr)
|
|
else:
|
|
return cExpr
|
|
elif type(exprtype) is AbsApi.EnumType:
|
|
cppEnumName = exprtype.translate(self.langTranslator, namespace=usedNamespace)
|
|
return '({0}){1}'.format(cppEnumName, cExpr)
|
|
elif type(exprtype) is AbsApi.ClassType:
|
|
cppReturnType = exprtype.translate(self.langTranslator, namespace=usedNamespace)
|
|
if exprtype.desc.refcountable:
|
|
cppReturnType = CppTranslator.sharedPtrTypeExtractor.match(cppReturnType).group(2)
|
|
|
|
if type(exprtype.parent) is AbsApi.Method and len(exprtype.parent.name.words) >=1 and (exprtype.parent.name.words == ['new'] or exprtype.parent.name.words[0] == 'create'):
|
|
return 'Object::cPtrToSharedPtr<{0}>({1}, false)'.format(cppReturnType, cExpr)
|
|
else:
|
|
return 'Object::cPtrToSharedPtr<{0}>({1})'.format(cppReturnType, cExpr)
|
|
else:
|
|
if exprtype.isref:
|
|
return '{0}({1})'.format(exprtype.desc.name.to_camel_case(), cExpr)
|
|
else:
|
|
return '{0}(StructWrapper<::{1}>({2}).ptr())'.format(
|
|
exprtype.desc.name.to_camel_case(),
|
|
exprtype.desc.name.to_c(),
|
|
cExpr)
|
|
elif type(exprtype) is AbsApi.ListType:
|
|
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 = exprtype.containedTypeDesc.translate(self.langTranslator, namespace=usedNamespace)
|
|
if exprtype.containedTypeDesc.desc.refcountable:
|
|
cppReturnType = CppTranslator.sharedPtrTypeExtractor.match(cppReturnType).group(2)
|
|
return 'ObjectBctbxListWrapper<{0}>::bctbxListToCppList({1})'.format(cppReturnType, cExpr)
|
|
else:
|
|
cType = exprtype.containedTypeDesc.desc.name.to_c()
|
|
return 'StructBctbxListWrapper<{0},{1}>::bctbxListToCppList({2})'.format(cppReturnType, cType, cExpr)
|
|
else:
|
|
raise AbsApi.Error('translation of bctbx_list_t of enums or basic C types is not supported')
|
|
else:
|
|
return cExpr
|
|
|
|
@staticmethod
|
|
def fail(obj):
|
|
raise AbsApi.Error('Cannot translate {0} type'.format(type(obj)))
|
|
|
|
|
|
class EnumsHeader(object):
|
|
def __init__(self, translator):
|
|
self.translator = translator
|
|
self.enums = []
|
|
|
|
def add_enum(self, enum):
|
|
self.enums.append(self.translator.translate_enum(enum))
|
|
|
|
|
|
class ClassHeader(object):
|
|
def __init__(self, _class, translator):
|
|
if type(_class) is AbsApi.Class:
|
|
self._class = translator.translate_class(_class)
|
|
else:
|
|
self._class = translator.translate_interface(_class)
|
|
|
|
self.rootNs = translator.rootNs
|
|
self.define = '_{0}_HH'.format(_class.name.to_snake_case(upper=True, fullName=True))
|
|
self.filename = '{0}.hh'.format(_class.name.to_snake_case())
|
|
self.priorDeclarations = []
|
|
self.private_type = _class.name.to_camel_case(fullName=True)
|
|
|
|
self.includes = {'internal': [], 'external': []}
|
|
includes = self.needed_includes(_class)
|
|
|
|
for include in includes['external']:
|
|
self.includes['external'].append({'name': include})
|
|
|
|
for include in includes['internal']:
|
|
self.includes['internal'].append({'name': include})
|
|
|
|
def needed_includes(self, _class):
|
|
includes = {'internal': [], 'external': []}
|
|
|
|
if type(_class) is AbsApi.Class:
|
|
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
|
|
else:
|
|
methods = _class.methods
|
|
|
|
for method in methods:
|
|
self._needed_includes_from_type(method.returnType, includes)
|
|
for arg in method.args:
|
|
self._needed_includes_from_type(arg.type, includes)
|
|
|
|
if isinstance(_class, AbsApi.Class) and _class.listenerInterface is not None:
|
|
decl = 'class ' + _class.listenerInterface.name.translate(metaname.Translator.get('Cpp'))
|
|
self._add_prior_declaration(decl)
|
|
|
|
currentClassInclude = _class.name.to_snake_case()
|
|
if currentClassInclude in includes['internal']:
|
|
includes['internal'].remove(currentClassInclude)
|
|
|
|
return includes
|
|
|
|
def _needed_includes_from_method(self, method, includes):
|
|
self._needed_includes_from_type(method.returnType, includes)
|
|
for arg in method.args:
|
|
self._needed_includes_from_type(arg.type, includes)
|
|
|
|
def _needed_includes_from_type(self, type_, includes):
|
|
translator = metaname.Translator.get('Cpp')
|
|
if isinstance(type_, AbsApi.ClassType):
|
|
class_ = type_.desc
|
|
if class_.parent == self.rootNs:
|
|
decl = 'class ' + class_.name.translate(translator)
|
|
self._add_prior_declaration(decl)
|
|
else:
|
|
rootClass = class_.find_first_ancestor_by_type(AbsApi.Namespace, priorAncestor=True)
|
|
self._add_include(includes, 'internal', rootClass.name.to_snake_case())
|
|
elif isinstance(type_, AbsApi.EnumType):
|
|
enum = type_.desc
|
|
if enum.parent == self.rootNs:
|
|
headerFile = 'enums'
|
|
else:
|
|
rootClass = enum.find_first_ancestor_by_type(AbsApi.Namespace, priorAncestor=True)
|
|
headerFile = rootClass.name.to_snake_case()
|
|
self._add_include(includes, 'internal', headerFile)
|
|
elif isinstance(type_, AbsApi.BaseType):
|
|
if type_.name == 'integer' and isinstance(type_.size, int):
|
|
self._add_include(includes, 'external', 'cstdint')
|
|
elif type_.name == 'string':
|
|
self._add_include(includes, 'external', 'string')
|
|
elif isinstance(type_, AbsApi.ListType):
|
|
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)
|
|
|
|
def _add_prior_declaration(self, decl):
|
|
if next((x for x in self.priorDeclarations if x['declaration']==decl), None) is None:
|
|
self.priorDeclarations.append({'declaration': decl})
|
|
|
|
|
|
class MainHeader(object):
|
|
def __init__(self):
|
|
self.includes = []
|
|
self.define = '_LINPHONE_HH'
|
|
|
|
def add_include(self, include):
|
|
self.includes.append({'name': include})
|
|
|
|
|
|
class ClassImpl(object):
|
|
def __init__(self):
|
|
self.classes = []
|
|
self.namespace = 'linphone'
|
|
|
|
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.parser.namespace)
|
|
self.renderer = pystache.Renderer()
|
|
self.mainHeader = MainHeader()
|
|
self.impl = ClassImpl()
|
|
|
|
def render_all(self):
|
|
header = EnumsHeader(self.translator)
|
|
|
|
for enum in self.parser.namespace.enums:
|
|
header.add_enum(enum)
|
|
|
|
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:
|
|
header = ClassHeader(_class, self.translator)
|
|
headerName = _class.name.to_snake_case() + '.hh'
|
|
self.mainHeader.add_include(headerName)
|
|
self.render(header, self.includedir + '/' + header.filename)
|
|
|
|
if type(_class) is not AbsApi.Interface:
|
|
self.impl.classes.append(header._class)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
try:
|
|
argparser = argparse.ArgumentParser(description='Generate source files for the C++ wrapper')
|
|
argparser.add_argument('xmldir', type=str, help='Directory where the XML documentation of the Linphone\'s API generated by Doxygen is placed')
|
|
argparser.add_argument('-o --output', type=str, help='the directory where to generate the source files', dest='outputdir', default='.')
|
|
argparser.add_argument('-v --verbose', help='Show warning and info traces.', action='store_true', default=False, dest='verbose_mode')
|
|
argparser.add_argument('-d --debug', help='Show all traces.', action='store_true', default=False, dest='debug_mode')
|
|
args = argparser.parse_args()
|
|
|
|
if args.debug_mode:
|
|
loglevel = logging.DEBUG
|
|
elif args.verbose_mode:
|
|
loglevel = logging.INFO
|
|
else:
|
|
loglevel = logging.ERROR
|
|
logging.basicConfig(format='%(levelname)s[%(name)s]: %(message)s', level=loglevel)
|
|
|
|
includedir = args.outputdir + '/include/linphone++'
|
|
srcdir = args.outputdir + '/src'
|
|
if not os.path.exists(includedir):
|
|
os.makedirs(includedir)
|
|
if not os.path.exists(srcdir):
|
|
os.makedirs(srcdir)
|
|
|
|
genwrapper = GenWrapper(includedir, srcdir, args.xmldir)
|
|
genwrapper.render_all()
|
|
except AbsApi.Error as e:
|
|
logging.critical(e)
|