Wrappers generator: logging system reworking

This commit is contained in:
François Grisez 2017-11-22 11:16:06 +01:00
parent a2f363ac64
commit f6cd06d37d
16 changed files with 366 additions and 298 deletions

View file

@ -18,10 +18,11 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import sys
import os
import argparse
import logging
import os
import pystache
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'tools'))
import abstractapi
@ -363,7 +364,11 @@ if __name__ == '__main__':
argparser = argparse.ArgumentParser(description='Generate a sphinx project to generate the documentation of Linphone Core API.')
argparser.add_argument('xmldir', type=str, help='directory holding the XML documentation of the C API generated by Doxygen')
argparser.add_argument('-o --output', type=str, help='directory into where Sphinx source files will be written', dest='outputdir', default='.')
argparser.add_argument('-v --verbose', action='store_true', default=False, dest='verbose_mode', help='Show warning and info messages')
args = argparser.parse_args()
loglevel = logging.INFO if args.verbose_mode else logging.ERROR
logging.basicConfig(format='%(levelname)s[%(name)s]: %(message)s', level=loglevel)
cProject = capi.Project()
cProject.initFromDir(args.xmldir)

View file

@ -350,26 +350,23 @@ LINPHONE_PUBLIC void linphone_call_set_audio_route (LinphoneCall *call, Linphone
LINPHONE_PUBLIC int linphone_call_get_stream_count (const LinphoneCall *call);
/**
* Returns the type of stream for the given stream index.
* @param call
* @param stream_index
* @brief Returns the type of stream for the given stream index.
* @return the type (MSAudio, MSVideo, MSText) of the stream of given index.
* @donotwrap
**/
LINPHONE_PUBLIC MSFormatType linphone_call_get_stream_type (const LinphoneCall *call, int stream_index);
/**
* Returns the meta rtp transport for the given stream index.
* @param call
* @param stream_index
* @return a pointer to the meta rtp transport if it exists, NULL otherwise
* @brief Returns the meta rtp transport for the given stream index.
* @return a pointer to the meta rtp transport if it exists, NULL otherwise.
* @donotwrap
**/
LINPHONE_PUBLIC RtpTransport *linphone_call_get_meta_rtp_transport (const LinphoneCall *call, int stream_index);
/**
* Returns the meta rtcp transport for the given stream index.
* @param call
* @param stream_index
* @return a pointer to the meta rtcp transport if it exists, NULL otherwise
* @brief Returns the meta rtcp transport for the given stream index.
* @return a pointer to the meta rtcp transport if it exists, NULL otherwise.
* @donotwrap
**/
LINPHONE_PUBLIC RtpTransport *linphone_call_get_meta_rtcp_transport (const LinphoneCall *call, int stream_index);

View file

@ -68,6 +68,7 @@ LINPHONE_PUBLIC const LinphoneAddress * linphone_call_log_get_from_address(const
* Get the RTP statistics computed locally regarding the call.
* @param[in] cl LinphoneCallLog object
* @return The RTP statistics that have been computed locally for the call.
* @donotwrap
**/
LINPHONE_PUBLIC const rtp_stats_t * linphone_call_log_get_local_stats(const LinphoneCallLog *cl);
@ -101,6 +102,7 @@ LINPHONE_PUBLIC LinphoneAddress * linphone_call_log_get_remote_address(const Lin
* @note Not implemented yet.
* @param[in] cl LinphoneCallLog object
* @return The RTP statistics that have been computed by the remote end for the call.
* @donotwrap
**/
LINPHONE_PUBLIC const rtp_stats_t * linphone_call_log_get_remote_stats(const LinphoneCallLog *cl);

View file

@ -140,10 +140,11 @@ LINPHONE_PUBLIC float linphone_call_params_get_received_framerate(const Linphone
LINPHONE_PUBLIC const LinphoneVideoDefinition * linphone_call_params_get_received_video_definition(const LinphoneCallParams *cp);
/**
* Get the size of the video that is received.
* @param[in] cp LinphoneCallParams object
* @brief Get the size of the video that is received.
* @param[in] cp #LinphoneCallParams object
* @return The received video size or MS_VIDEO_SIZE_UNKNOWN if not available.
* @deprecated Use linphone_call_params_get_received_video_definition() instead
* @deprecated Use #linphone_call_params_get_received_video_definition() instead. Deprecated since 2017-03-28.
* @donotwrap
*/
LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp);
@ -176,10 +177,11 @@ LINPHONE_PUBLIC float linphone_call_params_get_sent_framerate(const LinphoneCall
LINPHONE_PUBLIC const LinphoneVideoDefinition * linphone_call_params_get_sent_video_definition(const LinphoneCallParams *cp);
/**
* Gets the size of the video that is sent.
* @param[in] cp LinphoneCalParams object
* @biref Gets the size of the video that is sent.
* @param[in] cp #LinphoneCalParams object
* @return The sent video size or MS_VIDEO_SIZE_UNKNOWN if not available.
* @deprecated Use linphone_call_params_get_sent_video_definition() instead
* @deprecated Use #linphone_call_params_get_sent_video_definition() instead. Deprecated since 2017-03-28.
* @donotwrap
*/
LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp);

View file

@ -193,22 +193,25 @@ typedef struct _LinphoneCoreVTable{
} LinphoneCoreVTable;
/**
* Instantiate a vtable with all arguments set to NULL
* @return newly allocated vtable
* @brief Instantiate a vtable with all arguments set to NULL.
* @return newly allocated vtable.
* @donotwrap
*/
LINPHONE_PUBLIC LinphoneCoreVTable *linphone_core_v_table_new(void);
/**
* Sets a user data pointer in the vtable.
* @param table the vtable
* @param data the user data to attach
* @brief Sets a user data pointer in the vtable.
* @param table the vtable.
* @param data the user data to attach.
* @donotwrap
*/
LINPHONE_PUBLIC void linphone_core_v_table_set_user_data(LinphoneCoreVTable *table, void *data);
/**
* Gets a user data pointer in the vtable.
* @param table the vtable
* @return the data attached to the vtable
* @brief Gets a user data pointer in the vtable.
* @param table the vtable.
* @return the data attached to the vtable.
* @donotwrap
*/
LINPHONE_PUBLIC void* linphone_core_v_table_get_user_data(const LinphoneCoreVTable *table);
@ -222,8 +225,9 @@ LINPHONE_PUBLIC void* linphone_core_v_table_get_user_data(const LinphoneCoreVTab
LINPHONE_PUBLIC LinphoneCoreVTable *linphone_core_get_current_vtable(LinphoneCore *lc);
/**
* Destroy a vtable.
* @param table to be destroyed
* @brief Destroy a vtable.
* @param table to be destroyed.
* @donotwrap
*/
LINPHONE_PUBLIC void linphone_core_v_table_destroy(LinphoneCoreVTable* table);
@ -786,25 +790,25 @@ LINPHONE_PUBLIC char * linphone_core_compress_log_collection(void);
LINPHONE_PUBLIC void linphone_core_reset_log_collection(void);
/**
* Define a log handler.
*
* @bref Define a log handler.
* @param logfunc The function pointer of the log handler.
* @donotwrap
*/
LINPHONE_PUBLIC void linphone_core_set_log_handler(OrtpLogFunc logfunc);
/**
* Define a log file.
* @brief Define a log file.
*
* If the file pointer passed as an argument is NULL, stdout is used instead.
*
* @param file A pointer to the FILE structure of the file to write to.
* @donotwrap
*/
LINPHONE_PUBLIC void linphone_core_set_log_file(FILE *file);
/**
* Define the minimum level for logging.
*
* @brief Define the minimum level for logging.
* @param loglevel Minimum level for logging messages.
* @donotwrap
**/
LINPHONE_PUBLIC void linphone_core_set_log_level(OrtpLogLevel loglevel);
@ -3303,7 +3307,8 @@ LINPHONE_PUBLIC bool_t linphone_core_video_display_enabled(LinphoneCore *lc);
* @param[in] lc LinphoneCore object
* @param[in] policy The video policy to use
* @ingroup media_parameters
* @deprecated
* @deprecated Deprecated since 2017-04-19.
* @donotwrap
**/
LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_video_policy(LinphoneCore *lc, const LinphoneVideoPolicy *policy);
@ -3313,7 +3318,8 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_video_policy(Linphone
* @param[in] lc LinphoneCore object
* @return The video policy being used
* @ingroup media_parameters
* @deprecated
* @deprecated Deprecated since 2017-04-19.
* @donotwrap
**/
LINPHONE_PUBLIC LINPHONE_DEPRECATED const LinphoneVideoPolicy *linphone_core_get_video_policy(const LinphoneCore *lc);
@ -3400,9 +3406,10 @@ LINPHONE_PUBLIC void linphone_core_set_video_activation_policy(LinphoneCore *lc,
LINPHONE_PUBLIC LinphoneVideoActivationPolicy *linphone_core_get_video_activation_policy(const LinphoneCore *lc);
/**
* Returns the zero terminated table of supported video resolutions.
* @brief Returns the zero terminated table of supported video resolutions.
* @ingroup media_parameters
* @deprecated Use linphone_factory_get_supported_video_definitions() instead
* @deprecated Use #linphone_factory_get_supported_video_definitions() instead. Deprecated since 2017-03-28.
* @donotwrap
**/
LINPHONE_PUBLIC LINPHONE_DEPRECATED const MSVideoSizeDef *linphone_core_get_supported_video_sizes(LinphoneCore *lc);
@ -3416,12 +3423,13 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED const MSVideoSizeDef *linphone_core_get_supp
LINPHONE_PUBLIC void linphone_core_set_preferred_video_definition(LinphoneCore *lc, LinphoneVideoDefinition *vdef);
/**
* Sets the preferred video size.
* @brief Sets the preferred video size.
*
* This applies only to the stream that is captured and sent to the remote party,
* since we accept all standard video size on the receive path.
* @ingroup media_parameters
* @deprecated Use linphone_core_set_preferred_video_definition() instead
* @deprecated Use linphone_core_set_preferred_video_definition() instead. Deprecated since 2017-03-28.
* @donotwrap
**/
LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize);
@ -3437,14 +3445,16 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_preferred_video_size(
LINPHONE_PUBLIC void linphone_core_set_preview_video_definition(LinphoneCore *lc, LinphoneVideoDefinition *vdef);
/**
* Sets the video size for the captured (preview) video.
* @biref Sets the video size for the captured (preview) video.
*
* This method is for advanced usage where a video capture must be set independently of the size of the stream actually sent through the call.
* This allows for example to have the preview window with HD resolution even if due to bandwidth constraint the sent video size is small.
* Using this feature increases the CPU consumption, since a rescaling will be done internally.
* @ingroup media_parameters
* @param lc the linphone core
* @param vsize the video resolution choosed for capuring and previewing. It can be (0,0) to not request any specific preview size and let the core optimize the processing.
* @deprecated Use linphone_core_set_preview_video_definition() instead
* @deprecated Use #linphone_core_set_preview_video_definition() instead. Deprecated since 2017-03-28.
* @donotwrap
**/
LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize);
@ -3467,12 +3477,13 @@ LINPHONE_PUBLIC void linphone_core_set_preview_video_size_by_name(LinphoneCore *
LINPHONE_PUBLIC const LinphoneVideoDefinition * linphone_core_get_preview_video_definition(const LinphoneCore *lc);
/**
* Returns video size for the captured video if it was previously set by linphone_core_set_preview_video_size(), otherwise returns a 0,0 size.
* @see linphone_core_set_preview_video_size()
* @brief Returns video size for the captured video if it was previously set by #linphone_core_set_preview_video_size(), otherwise returns a 0,0 size.
* @see #linphone_core_set_preview_video_size()
* @ingroup media_parameters
* @param lc the core
* @return a MSVideoSize
* @deprecated Use linphone_core_get_preview_video_definition() instead
* @return a #MSVideoSize
* @deprecated Use #linphone_core_get_preview_video_definition() instead. Since 2017-03-28.
* @donotwrap
**/
LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_core_get_preview_video_size(const LinphoneCore *lc);
@ -3487,13 +3498,15 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_core_get_preview_video_
LINPHONE_PUBLIC LinphoneVideoDefinition * linphone_core_get_current_preview_video_definition(const LinphoneCore *lc);
/**
* Returns the effective video size for the captured video as provided by the camera.
* @brief Returns the effective video size for the captured video as provided by the camera.
*
* When preview is disabled or not yet started, this function returns a zeroed video size.
* @see linphone_core_set_preview_video_size()
* @see #linphone_core_set_preview_video_size()
* @ingroup media_parameters
* @param lc the core
* @return a MSVideoSize
* @deprecated Use linphone_core_get_current_preview_video_definition() instead
* @return a #MSVideoSize
* @deprecated Use #linphone_core_get_current_preview_video_definition() instead. Deprecated since 2017-03-28.
* @donotwrap
**/
LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_core_get_current_preview_video_size(const LinphoneCore *lc);
@ -3506,9 +3519,10 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_core_get_current_previe
LINPHONE_PUBLIC const LinphoneVideoDefinition * linphone_core_get_preferred_video_definition(const LinphoneCore *lc);
/**
* Returns the current preferred video size for sending.
* @brief Returns the current preferred video size for sending.
* @ingroup media_parameters
* @deprecated Use linphone_core_get_preferred_video_definition() instead
* @deprecated Use linphone_core_get_preferred_video_definition() instead. Deprecated since 2017-03-28.
* @donotwrap
**/
LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_core_get_preferred_video_size(const LinphoneCore *lc);
@ -4708,24 +4722,27 @@ LINPHONE_PUBLIC void linphone_core_enable_video_multicast(LinphoneCore *core, bo
LINPHONE_PUBLIC bool_t linphone_core_video_multicast_enabled(const LinphoneCore *core);
/**
* Set the network simulator parameters.
* @brief Set the network simulator parameters.
*
* Liblinphone has the capabability of simulating the effects of a network (latency, lost packets, jitter, max bandwidth).
* Please refer to the oRTP documentation for the meaning of the parameters of the OrtpNetworkSimulatorParams structure.
* This function has effect for future calls, but not for currently running calls, though this behavior may be changed in future versions.
* @warning Due to design of network simulation in oRTP, simulation is applied independently for audio and video stream. This means for example that a bandwidth
* limit of 250kbit/s will have no effect on an audio stream running at 40kbit/s while a videostream targetting 400kbit/s will be highly affected.
* @param lc the LinphoneCore
* @param lc the #LinphoneCore
* @param params the parameters used for the network simulation.
* @return 0 if successful, -1 otherwise.
* @ingroup media_parameters
* @donotwrap
**/
LINPHONE_PUBLIC LinphoneStatus linphone_core_set_network_simulator_params(LinphoneCore *lc, const OrtpNetworkSimulatorParams *params);
/**
* Get the previously set network simulation parameters.
* @brief Get the previously set network simulation parameters.
* @see linphone_core_set_network_simulator_params
* @return a OrtpNetworkSimulatorParams structure.
* @return a #OrtpNetworkSimulatorParams structure.
* @ingroup media_parameters
* @donotwrap
**/
LINPHONE_PUBLIC const OrtpNetworkSimulatorParams *linphone_core_get_network_simulator_params(const LinphoneCore *lc);
@ -4862,6 +4879,7 @@ LINPHONE_PUBLIC const char *linphone_core_get_tls_key_path(const LinphoneCore *l
* @param lc LinphoneCore object
* @param imee LinphoneImEncryptionEngine object
* @ingroup chatroom
* @donotwrap
*/
LINPHONE_PUBLIC void linphone_core_set_im_encryption_engine(LinphoneCore *lc, LinphoneImEncryptionEngine *imee);
@ -4870,6 +4888,7 @@ LINPHONE_PUBLIC void linphone_core_set_im_encryption_engine(LinphoneCore *lc, Li
* @param lc LinphoneCore object
* @return the IM Encryption Engine in the core or NULL
* @ingroup chatroom
* @donotwrap
*/
LINPHONE_PUBLIC LinphoneImEncryptionEngine * linphone_core_get_im_encryption_engine(const LinphoneCore *lc);

View file

@ -55,12 +55,12 @@ LINPHONE_DEPRECATED typedef void (*LinphoneEcCalibrationAudioInit)(void *data);
LINPHONE_DEPRECATED typedef void (*LinphoneEcCalibrationAudioUninit)(void *data);
/**
*
* @brief Starts an echo calibration of the sound devices, in order to find adequate settings for the echo canceler automatically.
* @deprecated Use #linphone_core_start_echo_canceller_calibration() instead. To set the callbacks create or get an already instantiated
* #LinphoneCoreCbs and call #linphone_core_cbs_set_ec_calibration_result(), #linphone_core_cbs_set_ec_calibration_audio_init() and
* #linphone_core_cbs_set_ec_callibration_audio_uninit(). Deprecated since 2017-10-16.
* @ingroup misc
* @donotwrap
**/
LINPHONE_DEPRECATED LINPHONE_PUBLIC int linphone_core_start_echo_calibration(LinphoneCore *lc, LinphoneEcCalibrationCallback cb,
LinphoneEcCalibrationAudioInit audio_init_cb, LinphoneEcCalibrationAudioUninit audio_uninit_cb, void *cb_data);

View file

@ -245,12 +245,14 @@ LINPHONE_PUBLIC const char** linphone_config_get_sections_names(LinphoneConfig *
LINPHONE_PUBLIC const bctbx_list_t * linphone_config_get_sections_names_list(LpConfig *lpconfig);
/**
* Call a function for each section present in the configuration.
* @brief Call a function for each section present in the configuration.
* @donotwrap
**/
void linphone_config_for_each_section(const LinphoneConfig *lpconfig, void (*callback)(const char *section, void *ctx), void *ctx);
/**
* Call a function for each entry present in a section configuration.
* @brief Call a function for each entry present in a section configuration.
* @donotwrap
**/
void linphone_config_for_each_entry(const LinphoneConfig *lpconfig, const char *section, void (*callback)(const char *entry, void *ctx), void *ctx);

View file

@ -172,6 +172,7 @@ LINPHONE_PUBLIC void linphone_nat_policy_resolve_stun_server(LinphoneNatPolicy *
* WARNING: This function may block for up to 1 second.
* @param[in] policy LinphoneNatPolicy object
* @return addrinfo representation of the STUN server address.
* @donotwrap
*/
LINPHONE_PUBLIC const struct addrinfo * linphone_nat_policy_get_stun_server_addrinfo(LinphoneNatPolicy *policy);

View file

@ -19,13 +19,65 @@
import re
import genapixml as CApi
import metaname
import logging
class Error(RuntimeError):
pass
logger = logging.getLogger(__name__)
class BlacklistedException(Error):
class Error(Exception):
@property
def reason(self):
return self.args[0]
def __str__(self):
return str(self.reason)
@staticmethod
def _name_get_type_as_string(name):
if type(name) is metaname.ClassName:
return 'class'
elif type(name) is metaname.EnumName:
return 'enum'
elif type(name) is metaname.EnumeratorName:
return 'enumerator'
elif type(name) is metaname.MethodName:
return 'function'
else:
raise TypeError('{0} not handled'.format(type(name)))
class ParsingError(Error):
@property
def context(self):
return self.args[1] if len(self.args) >= 2 else None
def __str__(self):
if self.context is None:
return Error.__str__(self)
else:
params = {
'reason': self.reason,
'name': self.context.to_c(addBrackets=True),
'type_': Error._name_get_type_as_string(self.context)
}
return "error while parsing {name} {type_}: {reason}".format(**params)
class BlacklistedSymbolError(Error):
@property
def name(self):
return self.args[0]
def __str__(self):
params = {
'name': self.name.to_c(addBrackets=True),
'type_': Error._name_get_type_as_string(self.name)
}
return "{name} {type_} has been blacklisted".format(**params)
class TranslationError(Error):
pass
@ -154,7 +206,7 @@ class DocumentableObject(Object):
if isinstance(self, (Namespace,Enum,Class)):
return self
elif self.parent is None:
raise Error('{0} is not attached to a namespace object'.format(self))
return None
else:
return self.parent.get_namespace_object()
@ -424,17 +476,14 @@ class CParser(object):
for enum in self.cProject.enums:
try:
self.parse_enum(enum)
except Error as e:
print('Could not parse \'{0}\' enum: {1}'.format(enum.name, e.args[0]))
except BlacklistedSymbolError as e:
logger.debug(e)
for _class in self.cProject.classes:
for class_ in self.cProject.classes:
try:
self.parse_class(_class)
except BlacklistedException:
pass
except Error as e:
print('Could not parse \'{0}\' class: {1}'.format(_class.name, e.args[0]))
self.parse_class(class_)
except BlacklistedSymbolError as e:
logger.debug(e)
self._clean_all_indexes()
self._sortall()
@ -504,8 +553,8 @@ class CParser(object):
self._fix_type(method.returnType)
for arg in method.args:
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]))
except ParsingError as e:
raise ParsingError(e, method.name)
def _fix_type(self, _type):
if isinstance(_type, EnumType) and _type.desc is None:
@ -526,7 +575,7 @@ class CParser(object):
if _type.containedTypeName is not None:
_type.containedTypeDesc = self.parse_c_base_type(_type.containedTypeName)
else:
raise Error('bctbx_list_t type without specified contained type')
raise ParsingError('bctbx_list_t type without specified contained type')
def _fix_all_docs(self):
for _class in self.classesIndex.values():
@ -545,13 +594,8 @@ class CParser(object):
obj.detailedDescription.resolve_all_references(self)
def parse_enum(self, cenum):
if 'associatedTypedef' in dir(cenum):
nameStr = cenum.associatedTypedef.name
else:
nameStr = cenum.name
name = metaname.EnumName()
name.from_camel_case(nameStr, namespace=self.namespace.name)
name.from_camel_case(cenum.publicName, namespace=self.namespace.name)
enum = Enum(name)
enum.briefDescription = cenum.briefDoc
enum.detailedDescription = cenum.detailedDoc
@ -567,16 +611,21 @@ class CParser(object):
try:
aEnumValue.value_from_string(cEnumValue.value)
except ValueError:
raise Error('{0} enum value has an invalid definition ({1})'.format(cEnumValue.name, cEnumValue.value))
reason = '{0} enum value has an invalid definition ({1})'.format(cEnumValue.name, cEnumValue.value)
context = metaname.EnumeratorName()
context.from_camel_case(cEnumValue.name)
raise ParsingError(reason, context)
enum.add_enumerator(aEnumValue)
self.enumsIndex[nameStr] = enum
self.enumsIndex[cenum.publicName] = enum
self.enums.append(enum)
return enum
def parse_class(self, cclass):
if cclass.name in self.classBl:
raise BlacklistedException('{0} is blacklisted'.format(cclass.name));
name = metaname.ClassName()
name.from_snake_case(cclass.name)
raise BlacklistedSymbolError(name)
if cclass.name.endswith('Cbs'):
_class = self._parse_listener(cclass)
@ -603,8 +652,8 @@ class CParser(object):
_class.add_property(absProperty)
else:
_class.listenerInterface = self.interfacesIndex[cproperty.getter.returnArgument.ctype]
except Error as e:
print('Could not parse {0} property in {1}: {2}'.format(cproperty.name, cclass.name, e.args[0]))
except BlacklistedSymbolError as e:
logger.debug(e)
for cMethod in cclass.instanceMethods.values():
try:
@ -617,20 +666,15 @@ class CParser(object):
pass
else:
_class.add_instance_method(method)
except BlacklistedException:
pass
except Error as e:
print('Could not parse {0} function: {1}'.format(cMethod.name, e.args[0]))
except BlacklistedSymbolError as e:
logger.debug(e)
for cMethod in cclass.classMethods.values():
try:
method = self.parse_method(cMethod, type=Method.Type.Class, namespace=name)
_class.add_class_method(method)
except BlacklistedException:
pass
except Error as e:
print('Could not parse {0} function: {1}'.format(cMethod.name, e.args[0]))
except BlacklistedSymbolError as e:
logger.debug(e)
return _class
@ -652,27 +696,28 @@ class CParser(object):
def _parse_listener(self, cclass):
name = metaname.InterfaceName()
name.from_camel_case(cclass.name, namespace=self.namespace.name)
if name.words[len(name.words)-1] == 'cbs':
name.words[len(name.words)-1] = 'listener'
else:
raise Error('{0} is not a listener'.format(cclass.name))
listener = Interface(name)
listener.briefDescription = cclass.briefDoc
listener.detailedDescription = cclass.detailedDoc
for property in cclass.properties.values():
if property.name != 'user_data':
try:
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]))
return listener
try:
name = metaname.InterfaceName()
name.from_camel_case(cclass.name, namespace=self.namespace.name)
name.words[-1] = 'listener'
listener = Interface(name)
listener.briefDescription = cclass.briefDoc
listener.detailedDescription = cclass.detailedDoc
for property in cclass.properties.values():
if property.name != 'user_data':
try:
method = self._parse_listener_property(property, listener, cclass.events)
listener.add_method(method)
except BlacklistedSymbolError as e:
logger.debug(e)
return listener
except ParsingError as e:
context = metaname.ClassName()
context.from_camel_case(cclass.name)
raise ParsingError(e, context)
def _parse_listener_property(self, property, listener, events):
methodName = metaname.MethodName()
@ -685,12 +730,12 @@ class CParser(object):
elif property.setter is not None and len(property.setter.arguments) == 2:
eventName = property.setter.arguments[1].ctype
else:
raise Error('event name for {0} property of {1} listener not found'.format(property.name, listener.name.to_snake_case(fullName=True)))
raise ParsingError('event name for {0} property of {1} listener not found'.format(property.name, listener.name.to_c()))
try:
event = events[eventName]
except KeyError:
raise Error('invalid event name \'{0}\''.format(eventName))
raise ParsingError('invalid event name \'{0}\''.format(eventName))
method = Method(methodName)
method.returnType = self.parse_type(event.returnArgument)
@ -706,27 +751,30 @@ class CParser(object):
name = metaname.MethodName()
name.from_snake_case(cfunction.name, namespace=namespace)
if self._is_blacklisted(name):
raise BlacklistedException('{0} is blacklisted'.format(name.to_c()));
method = Method(name, type=type)
method.briefDescription = cfunction.briefDoc
method.detailedDescription = cfunction.detailedDoc
method.deprecated = cfunction.deprecated
method.returnType = self.parse_type(cfunction.returnArgument)
for arg in cfunction.arguments:
if type == Method.Type.Instance and arg is cfunction.arguments[0]:
method.isconst = ('const' in arg.completeType.split(' '))
else:
aType = self.parse_type(arg)
argName = metaname.ArgName()
argName.from_snake_case(arg.name)
absArg = Argument(argName, aType)
method.add_arguments(absArg)
self.methodsIndex[cfunction.name] = method
return method
try:
if self._is_blacklisted(name):
raise BlacklistedSymbolError(name)
method = Method(name, type=type)
method.briefDescription = cfunction.briefDoc
method.detailedDescription = cfunction.detailedDoc
method.deprecated = cfunction.deprecated
method.returnType = self.parse_type(cfunction.returnArgument)
for arg in cfunction.arguments:
if type == Method.Type.Instance and arg is cfunction.arguments[0]:
method.isconst = ('const' in arg.completeType.split(' '))
else:
aType = self.parse_type(arg)
argName = metaname.ArgName()
argName.from_snake_case(arg.name)
absArg = Argument(argName, aType)
method.add_arguments(absArg)
self.methodsIndex[cfunction.name] = method
return method
except ParsingError as e:
raise ParsingError(e, name)
def parse_type(self, cType):
if cType.ctype in self.cBaseType or re.match(self.regexFixedSizeInteger, cType.ctype):
@ -742,7 +790,7 @@ class CParser(object):
elif cType.ctype.endswith('Mask'):
absType = BaseType('integer', isUnsigned=True)
else:
raise Error('Unknown C type \'{0}\''.format(cType.ctype))
raise ParsingError('Unknown C type \'{0}\''.format(cType.ctype))
absType.cDecl = cType.completeType
return absType
@ -791,7 +839,7 @@ class CParser(object):
elif 'isref' not in param or param['isref'] is False:
param['isref'] = True
else:
raise Error('Unhandled double-pointer')
raise ParsingError('Unhandled double-pointer')
else:
matchCtx = re.match(self.regexFixedSizeInteger, elem)
if matchCtx:
@ -801,13 +849,13 @@ class CParser(object):
param['size'] = int(matchCtx.group(2))
if param['size'] not in [8, 16, 32, 64]:
raise Error('{0} C basic type has an invalid size ({1})'.format(cDecl, param['size']))
raise ParsingError('{0} C basic type has an invalid size ({1})'.format(cDecl, param['size']))
if name is not None:
return BaseType(name, **param)
else:
raise Error('could not find type in \'{0}\''.format(cDecl))
raise ParsingError('could not find type in \'{0}\''.format(cDecl))
class Translator:
@ -935,7 +983,7 @@ class CppLangTranslator(CLikeLangTranslator):
if type(_type.parent) is Argument:
res += ' &'
else:
raise Error('\'{0}\' is not a base abstract type'.format(_type.name))
raise TranslationError('\'{0}\' is not a base abstract type'.format(_type.name))
if _type.isUnsigned:
if _type.name == 'integer' and isinstance(_type.size, int):
@ -953,7 +1001,7 @@ class CppLangTranslator(CLikeLangTranslator):
def translate_enum_type(self, _type, showStdNs=True, namespace=None):
if _type.desc is None:
raise Error('{0} has not been fixed'.format(_type.name))
raise TranslationError('{0} has not been fixed'.format(_type.name))
if namespace is not None:
nsName = namespace.name if namespace is not GlobalNs else None
@ -965,7 +1013,7 @@ class CppLangTranslator(CLikeLangTranslator):
def translate_class_type(self, _type, showStdNs=True, namespace=None):
if _type.desc is None:
raise Error('{0} has not been fixed'.format(_type.name))
raise TranslationError('{0} has not been fixed'.format(_type.name))
if namespace is not None:
nsName = namespace.name if namespace is not GlobalNs else None
@ -999,7 +1047,7 @@ class CppLangTranslator(CLikeLangTranslator):
def translate_list_type(self, _type, showStdNs=True, namespace=None):
if _type.containedTypeDesc is None:
raise Error('{0} has not been fixed'.format(_type.containedTypeName))
raise TranslationError('{0} has not been fixed'.format(_type.containedTypeName))
elif isinstance(_type.containedTypeDesc, BaseType):
res = _type.containedTypeDesc.translate(self)
else:
@ -1096,7 +1144,7 @@ class CSharpLangTranslator(CLikeLangTranslator):
else:
return 'IEnumerable<string>'
else:
raise Error('\'{0}\' is not a base abstract type'.format(_type.name))
raise TranslationError('\'{0}\' is not a base abstract type'.format(_type.name))
return res
@ -1117,15 +1165,15 @@ class CSharpLangTranslator(CLikeLangTranslator):
if _type.containedTypeDesc.name == 'string':
return 'IEnumerable<string>'
else:
raise Error('translation of bctbx_list_t of basic C types is not supported')
raise TranslationError('translation of bctbx_list_t of basic C types is not supported')
elif type(_type.containedTypeDesc) is ClassType:
ptrType = _type.containedTypeDesc.desc.name.translate(self.nameTranslator)
return 'IEnumerable<' + ptrType + '>'
else:
if _type.containedTypeDesc:
raise Error('translation of bctbx_list_t of enums')
raise TranslationError('translation of bctbx_list_t of enums')
else:
raise Error('translation of bctbx_list_t of unknow type !')
raise TranslationError('translation of bctbx_list_t of unknow type !')
def translate_argument(self, arg, dllImport=True):
return '{0} {1}'.format(

View file

@ -17,15 +17,20 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import argparse
import logging
import os
import six
import string
import sys
import xml.etree.ElementTree as ET
import xml.dom.minidom as minidom
import metadoc
logger = logging.getLogger(__name__)
class CObject:
def __init__(self, name):
self.name = name.strip()
@ -47,6 +52,10 @@ class CEnum(CObject):
CObject.__init__(self, name)
self.values = []
self.associatedTypedef = None
@property
def publicName(self):
return self.associatedTypedef.name if self.associatedTypedef is not None else self.name
def addValue(self, value):
self.values.append(value)
@ -239,7 +248,6 @@ class CClass(CObject):
class Project:
def __init__(self):
self.verbose = False
self.prettyPrint = False
self.enums = []
self.__structs = []
@ -251,37 +259,28 @@ class Project:
def add(self, elem):
if isinstance(elem, CClass):
if self.verbose:
print("Adding class " + elem.name)
logger.debug("Adding class " + elem.name)
self.classes.append(elem)
elif isinstance(elem, CEnum):
if self.verbose:
print("Adding enum " + elem.name)
for ev in elem.values:
print("\t" + ev.name)
msg = 'Adding enum {0}'.format(elem.name)
for value in elem.values:
msg += ('\t{0}'.format(value))
logger.debug(msg)
self.enums.append(elem)
elif isinstance(elem, CStruct):
if self.verbose:
print("Adding struct " + elem.name)
for sm in elem.members:
print("\t" + sm.ctype + " " + sm.name)
msg = "Adding struct " + elem.name
for sm in elem.members:
msg += ('\t{0} {1}'.format(sm.ctype, sm.name))
logger.debug(msg)
self.__structs.append(elem)
elif isinstance(elem, CTypedef):
if self.verbose:
print("Adding typedef " + elem.name)
print("\t" + elem.definition)
logger.debug('Adding typedef {0}\t{1}'.format(elem.name, elem.definition))
self.__typedefs.append(elem)
elif isinstance(elem, CEvent):
if self.verbose:
print("Adding event " + elem.name)
print("\tReturns: " + elem.returnArgument.ctype)
print("\tArguments: " + str(elem.arguments))
logger.debug('Adding event {0}\tReturns: {1}\tArguments: {2}'.format(elem.name, elem.returnArgument.ctype, elem.arguments))
self.__events.append(elem)
elif isinstance(elem, CFunction):
if self.verbose:
print("Adding function " + elem.name)
print("\tReturns: " + elem.returnArgument.ctype)
print("\tArguments: " + str(elem.arguments))
logger.debug('Adding event {0}\tReturns: {1}\tArguments: {2}'.format(elem.name, elem.returnArgument.ctype, elem.arguments))
self.__functions.append(elem)
def __cleanDescription(self, descriptionNode):
@ -330,7 +329,7 @@ class Project:
break
if not structFound:
name = td.definition[7:]
print("Structure with no associated typedef: " + name)
logger.warning("Structure with no associated typedef: " + name)
st = CStruct(name)
st.associatedTypedef = td
self.add(st)
@ -503,7 +502,7 @@ class Project:
if arg.description == None:
missingDocWarning += "\t'" + arg.name + "' parameter not documented\n";
if missingDocWarning != '':
print(name + ":\n" + missingDocWarning)
logger.warning(name + ":\n" + missingDocWarning)
f = CEvent(name, returnarg, argslist)
deprecatedNode = node.find(".//xrefsect[xreftitle='Deprecated']")
if deprecatedNode is not None:
@ -599,7 +598,7 @@ class Project:
if not f.location.endswith('.h'):
missingDocWarning += "\tNot documented in a header file ('" + f.location + "')\n";
if missingDocWarning != '':
print(name + ":\n" + missingDocWarning)
logger.warning(name + ":\n" + missingDocWarning)
return f
def __findCFunction(self, tree):
@ -614,11 +613,10 @@ class Project:
for f in xmlfiles:
tree = None
try:
if self.verbose:
print("Parsing XML file: " + f.name)
logger.debug("Parsing XML file: " + f)
tree = ET.parse(f)
except ET.ParseError as e:
print(e)
logger.error(e)
if tree is not None:
trees.append(tree)
for tree in trees:
@ -639,7 +637,7 @@ class Project:
for c in self.classes:
for name, p in six.iteritems(c.properties):
if p.getter is None and p.setter is not None:
print("Property '" + name + "' of class '" + c.name + "' has a setter but no getter")
logger.warning("Property '" + name + "' of class '" + c.name + "' has a setter but no getter")
class Generator:
@ -764,7 +762,7 @@ class Generator:
classNode.append(cclass.detailedDescription)
def generate(self, project):
print("Generating XML document of Linphone API to '" + self.__outputfile.name + "'")
logger.info("Generating XML document of Linphone API to '" + self.__outputfile.name + "'")
apiNode = ET.Element('api')
project.enums.sort(key = lambda e: e.name)
if len(project.enums) > 0:
@ -797,7 +795,9 @@ def main(argv = None):
args.outputfile = open('api.xml', 'w')
project = Project()
if args.verbose:
project.verbose = True
logger.setLogLevel(logging.DEBUG)
else:
logger.setLogLevel(logging.INFO)
if args.pretty:
project.prettyPrint = True
project.initFromDir(args.xmldir)

View file

@ -14,8 +14,10 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import metaname
import abstractapi
import logging
import metaname
import re
@ -146,7 +148,7 @@ class ClassReference(Reference):
try:
self.relatedObject = api.classesIndex[self.cname]
except KeyError:
print('doc reference pointing on an unknown object ({0})'.format(self.cname))
logging.warning('doc reference pointing on an unknown object ({0})'.format(self.cname))
class FunctionReference(Reference):
@ -154,7 +156,7 @@ class FunctionReference(Reference):
try:
self.relatedObject = api.methodsIndex[self.cname]
except KeyError:
print('doc reference pointing on an unknown object ({0})'.format(self.cname))
logging.warning('doc reference pointing on an unknown object ({0})'.format(self.cname))
class Paragraph(MultiChildTreeNode):
@ -443,8 +445,8 @@ class Translator:
strPara += part
else:
strPara += part.translate(self)
except TranslationError as e:
print('error: {0}'.format(e.msg()))
except ReferenceTranslationError:
strPara += part.cname
return strPara

View file

@ -144,7 +144,7 @@ class Name(object):
class ClassName(Name):
def to_c(self):
def to_c(self, addBrackets=False):
return self.to_camel_case(fullName=True)
def translate(self, translator, **params):
@ -152,7 +152,7 @@ class ClassName(Name):
class InterfaceName(ClassName):
def to_c(self):
def to_c(self, addBrackets=False):
return ClassName.to_c(self)[:-8] + 'Cbs'
def translate(self, translator, **params):
@ -183,16 +183,19 @@ class MethodName(Name):
self.overloadRef = int(suffix)
del self.words[-1]
def to_c(self):
def to_c(self, addBrackets=False):
suffix = ('_' + str(self.overloadRef)) if self.overloadRef > 0 else ''
return self.to_snake_case(fullName=True) + suffix
cName = self.to_snake_case(fullName=True) + suffix
if addBrackets:
cName += '()'
return cName
def translate(self, translator, **params):
return translator.translate_method_name(self, **params)
class ArgName(Name):
def to_c(self):
def to_c(self, addBrackets=False):
return self.to_snake_case()
def translate(self, translator, **params):

View file

@ -42,16 +42,12 @@ blacklisted_events = [
'LinphoneCoreTextMessageReceivedCb' # not respecting naming convention
]
blacklisted_functions = [
'linphone_call_log_get_local_stats', # missing rtp_stats_t
'linphone_call_log_get_remote_stats', # missing rtp_stats_t
'linphone_call_params_get_privacy', # missing LinphonePrivacyMask
'linphone_call_params_set_privacy', # missing LinphonePrivacyMask
'linphone_chat_message_start_file_download', # callback function in parameter
'linphone_chat_message_state_to_string', # There is no use to wrap this function
'linphone_chat_room_send_chat_message', # Use linphone_chat_room_send_chat_message_2 instead
'linphone_chat_room_send_message2', # callback function in parameter
'linphone_config_for_each_entry', # to be handwritten because of callback
'linphone_config_for_each_section', # to be handwritten because of callback
'linphone_config_get_range', # to be handwritten because of result via arguments
'linphone_config_load_dict_to_section', # missing LinphoneDictionary
'linphone_config_section_to_dict', # missing LinphoneDictionary
@ -62,10 +58,7 @@ blacklisted_functions = [
'linphone_core_enable_logs_with_cb', # callback function in parameter
'linphone_core_get_audio_port_range', # to be handwritten because of result via arguments
'linphone_core_get_default_proxy',
'linphone_core_get_network_simulator_params', # missing OrtpNetworkSimulatorParams
'linphone_core_get_supported_video_sizes', # missing MSVideoSizeDef
'linphone_core_get_tunnel', # blacklisted LinphoneTunnel
'linphone_core_get_video_policy', # missing LinphoneVideoPolicy
'linphone_core_get_video_port_range', # to be handwritten because of result via arguments
'linphone_core_new', # replaced by linphone_factory_create_core
'linphone_core_new_with_config', # replaced by linphone_factory_create_core_with_config
@ -75,13 +68,7 @@ blacklisted_functions = [
'linphone_core_set_log_collection_max_file_size', # need to handle class properties
'linphone_core_set_log_collection_path', # need to handle class properties
'linphone_core_set_log_collection_prefix', # need to handle class properties
'linphone_core_set_log_file', # There is no use to wrap this function
'linphone_core_set_log_handler', # Hand-written but put directly in the linphone module
'linphone_core_set_log_level', # There is no use to wrap this function
'linphone_core_set_log_level_mask', # There is no use to wrap this function
'linphone_core_set_network_simulator_params', # missing OrtpNetworkSimulatorParams
'linphone_core_set_video_policy', # missing LinphoneVideoPolicy
'linphone_nat_policy_get_stun_server_addrinfo',
'linphone_proxy_config_get_privacy', # missing LinphonePrivacyMask
'linphone_proxy_config_normalize_number', # to be handwritten because of result via arguments
'linphone_proxy_config_set_file_transfer_server', # defined but not implemented in linphone core

View file

@ -21,8 +21,10 @@ 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
@ -58,9 +60,12 @@ class CppTranslator(object):
def translate_enumerator(self, enumerator):
enumeratorDict = {
'name' : enumerator.name.translate(self.nameTranslator),
'doc' : enumerator.briefDescription.translate(self.docTranslator),
'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):
@ -92,8 +97,11 @@ class CppTranslator(object):
if _class.name.to_c() == 'LinphoneCore':
classDict['friendClasses'].append({'name': 'Factory'});
classDict['briefDoc'] = _class.briefDescription.translate(self.docTranslator, tagAsBrief=True)
classDict['detailedDoc'] = _class.detailedDescription.translate(self.docTranslator)
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)
@ -115,24 +123,15 @@ class CppTranslator(object):
classDict['currentCallbacksGetter'] = _class.name.to_snake_case(fullName=True) + '_get_current_callbacks'
for _property in _class.properties:
try:
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]))
classDict['methods'] += self.translate_property(_property)
for method in _class.instanceMethods:
try:
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]))
methodDict = self.translate_method(method)
classDict['methods'].append(methodDict)
for method in _class.classMethods:
try:
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]))
methodDict = self.translate_method(method)
classDict['staticMethods'].append(methodDict)
return classDict
@ -175,11 +174,8 @@ class CppTranslator(object):
'methods' : []
}
for method in interface.methods:
try:
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]))
methodDict = self.translate_method(method, genImpl=False)
intDict['methods'].append(methodDict)
return intDict
@ -199,10 +195,14 @@ class CppTranslator(object):
'implPrototype': method.translate_as_prototype(self.langTranslator, namespace=namespace),
'deprecated': method.deprecated,
'suffix': '',
'briefDoc': method.briefDescription.translate(self.docTranslator, tagAsBrief=True) if method.briefDescription is not None else None,
'detailedDoc': method.detailedDescription.translate(self.docTranslator) if method.detailedDescription is not None else None
}
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'] = ' {}'
@ -465,7 +465,7 @@ class GenWrapper(object):
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]))
logging.info('{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')
@ -491,44 +491,40 @@ class GenWrapper(object):
def render_header(self, _class):
if _class is not None:
try:
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)
except AbsApi.Error as e:
print('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0]))
def main():
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='.')
args = argparser.parse_args()
includedir = args.outputdir + '/include/linphone++'
srcdir = args.outputdir + '/src'
try:
os.makedirs(includedir)
except OSError as e:
if e.errno != errno.EEXIST:
print("Cannot create '{0}' directory: {1}".format(includedir, e.strerror))
sys.exit(1)
try:
os.makedirs(srcdir)
except OSError as e:
if e.errno != errno.EEXIST:
print("Cannot create '{0}' directory: {1}".format(srcdir, e.strerror))
sys.exit(1)
genwrapper = GenWrapper(includedir, srcdir, args.xmldir)
genwrapper.render_all()
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__':
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)

View file

@ -17,9 +17,10 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import argparse
import logging
import os
import sys
import pystache
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'tools'))
import genapixml as CApi
@ -401,20 +402,20 @@ class CsharpTranslator(object):
methodDict = self.translate_method(method, static=True, genImpl=True)
classDict['dllImports'].append(methodDict)
except AbsApi.Error as e:
print('Could not translate {0}: {1}'.format(method.name.to_c(), e.args[0]))
logging.error('Could not translate {0}: {1}'.format(method.name.to_c(), e.args[0]))
for prop in _class.properties:
try:
classDict['dllImports'] += self.translate_property(prop)
except AbsApi.Error as e:
print('error while translating {0} property: {1}'.format(prop.name.to_c(), e.args[0]))
logging.error('error while translating {0} property: {1}'.format(prop.name.to_c(), e.args[0]))
for method in _class.instanceMethods:
try:
methodDict = self.translate_method(method, static=False, genImpl=True)
classDict['dllImports'].append(methodDict)
except AbsApi.Error as e:
print('Could not translate {0}: {1}'.format(method.name.to_c(), e.args[0]))
logging.error('Could not translate {0}: {1}'.format(method.name.to_c(), e.args[0]))
return classDict
@ -469,12 +470,17 @@ def render(renderer, item, path):
f.write(content)
os.unlink(tmppath)
def main():
if __name__ == '__main__':
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('-n --name', type=str, help='the name of the genarated source file', dest='outputfile', default='LinphoneWrapper.cs')
argparser.add_argument('-v --verbose', action='store_true', dest='verbose_mode', default=False, help='Verbose mode.')
args = argparser.parse_args()
loglevel = logging.INFO if args.verbose_mode else logging.ERROR
logging.basicConfig(format='%(levelname)s[%(name)s]: %(message)s', level=loglevel)
entries = os.listdir(args.outputdir)
@ -504,7 +510,7 @@ def main():
impl = EnumImpl(item[1], translator)
enums.append(impl)
else:
print('warning: {0} enum won\'t be translated because of parsing errors'.format(item[0]))
logging.warning('{0} enum won\'t be translated because of parsing errors'.format(item[0]))
interfaces = []
classes = []
@ -519,10 +525,7 @@ def main():
impl = InterfaceImpl(_class, translator)
interfaces.append(impl)
except AbsApi.Error as e:
print('Could not translate {0}: {1}'.format(_class.name.to_c(), e.args[0]))
logging.error('Could not translate {0}: {1}'.format(_class.name.to_c(), e.args[0]))
wrapper = WrapperImpl(enums, interfaces, classes)
render(renderer, wrapper, args.outputdir + "/" + args.outputfile)
if __name__ == '__main__':
main()

View file

@ -18,13 +18,13 @@
# 02110-1301, USA.
import argparse
import os
import sys
import pystache
import errno
import logging
import os
import pystache
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'tools'))
print(sys.path)
import genapixml as CApi
import abstractapi as AbsApi
import metadoc
@ -456,7 +456,7 @@ class JavaTranslator(object):
classDict['methods'] += self.translate_property(_property)
classDict['jniMethods'] += self.translate_jni_property(_class.name, _property)
except AbsApi.Error as e:
print('error while translating {0} property: {1}'.format(_property.name.to_snake_case(), e.args[0]))
logging.error('error while translating {0} property: {1}'.format(_property.name.to_snake_case(), e.args[0]))
for method in _class.instanceMethods:
try:
@ -465,7 +465,7 @@ class JavaTranslator(object):
classDict['methods'].append(methodDict)
classDict['jniMethods'].append(jniMethodDict)
except AbsApi.Error as e:
print('Could not translate {0}: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0]))
logging.error('Could not translate {0}: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0]))
for method in _class.classMethods:
try:
@ -474,7 +474,7 @@ class JavaTranslator(object):
classDict['methods'].append(methodDict)
classDict['jniMethods'].append(jniMethodDict)
except AbsApi.Error as e:
print('Could not translate {0}: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0]))
logging.error('Could not translate {0}: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0]))
islistenable = _class.listenerInterface is not None
if islistenable:
@ -823,7 +823,7 @@ class GenWrapper(object):
self.jni.add_enum(value)
if name in ENUMS_LIST:
className = ENUMS_LIST[name]
print('Enum ' + name + ' belongs to class ' + className)
logging.info('Enum ' + name + ' belongs to class ' + className)
self.classes[className].add_enum(value)
self.enums_to_remove.append(name)
@ -859,7 +859,7 @@ class GenWrapper(object):
javaenum = JavaEnum(self.package, _class, self.translator)
self.enums[javaenum.className] = javaenum
except AbsApi.Error as e:
print('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0]))
logging.error('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0]))
def render_java_interface(self, _class):
if _class is not None:
@ -869,7 +869,7 @@ class GenWrapper(object):
javaInterfaceStub = JavaInterfaceStub(javainterface)
self.interfaces[javaInterfaceStub.classNameStub] = javaInterfaceStub
except AbsApi.Error as e:
print('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0]))
logging.error('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0]))
self.jni.add_callbacks(javainterface.className, javainterface.jniMethods)
def render_java_class(self, _class):
@ -878,20 +878,24 @@ class GenWrapper(object):
javaclass = JavaClass(self.package, _class, self.translator)
self.classes[javaclass.className] = javaclass
except AbsApi.Error as e:
print('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0]))
logging.error('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0]))
self.jni.add_methods(javaclass.className, javaclass.jniMethods)
##########################################################################
def main():
if __name__ == '__main__':
argparser = argparse.ArgumentParser(description='Generate source files for the Java 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('-p --package', type=str, help='the package name for the wrapper', dest='package', default='org.linphone.core')
argparser.add_argument('-n --name', type=str, help='the name of the genarated source file', dest='name', default='linphone_jni.cc')
argparser.add_argument('-e --exceptions', type=bool, help='enable the wrapping of LinphoneStatus into CoreException', dest='exceptions', default=False)
argparser.add_argument('-v --verbose', action='store_true', dest='verbose_mode', default=False, help='Verbose mode.')
args = argparser.parse_args()
loglevel = logging.INFO if args.verbose_mode else logging.ERROR
logging.basicConfig(format='%(levelname)s[%(name)s]: %(message)s', level=loglevel)
srcdir = args.outputdir + '/src'
javadir = args.outputdir + '/java'
package_dirs = args.package.split('.')
@ -902,18 +906,15 @@ def main():
os.makedirs(srcdir)
except OSError as e:
if e.errno != errno.EEXIST:
print("Cannot create '{0}' dircetory: {1}".format(srcdir, e.strerror))
logging.critical("Cannot create '{0}' dircetory: {1}".format(srcdir, e.strerror))
sys.exit(1)
try:
os.makedirs(javadir)
except OSError as e:
if e.errno != errno.EEXIST:
print("Cannot create '{0}' dircetory: {1}".format(javadir, e.strerror))
logging.critical("Cannot create '{0}' dircetory: {1}".format(javadir, e.strerror))
sys.exit(1)
genwrapper = GenWrapper(srcdir, javadir, args.package, args.xmldir, args.exceptions)
genwrapper.render_all()
if __name__ == '__main__':
main()