diff --git a/tools/python/apixml2python.py b/tools/python/apixml2python.py index 2e976abe9..da91429b5 100755 --- a/tools/python/apixml2python.py +++ b/tools/python/apixml2python.py @@ -23,7 +23,7 @@ import sys import xml.etree.ElementTree as ET sys.path.append(os.path.realpath(__file__)) -from apixml2python.linphone import LinphoneModule, HandWrittenClassMethod, HandWrittenInstanceMethod, HandWrittenProperty +from apixml2python.linphone import LinphoneModule, HandWrittenClassMethod, HandWrittenInstanceMethod, HandWrittenDeallocMethod, HandWrittenProperty blacklisted_classes = [ @@ -79,7 +79,8 @@ hand_written_functions = [ HandWrittenProperty('Core', 'sound_devices', 'linphone_core_get_sound_devices', None, "[list of string] Get the available sound devices."), HandWrittenProperty('Core', 'video_devices', 'linphone_core_get_video_devices', None, "[list of string] Get the available video capture devices."), HandWrittenClassMethod('Core', 'new', 'linphone_core_new', "Instantiate a LinphoneCore object.\n\n:param vtable: The callbacks.\n:type vtable: dictionary\n:param configPath: A path to a config file. If it does not exists it will be created. The config file is used to store all settings, call logs, friends, proxies... so that all these settings become persistent over the life of the LinphoneCore object. It is allowed to set to None. In that case LinphoneCore will not store any settings.\n:type configPath: string\n:param factoryConfigPath: A path to a read-only config file that can be used to store hard-coded preference such as proxy settings or internal preferences. The settings in this factory file always override the one in the normal config file. It is OPTIONAL, use None if unneeded.\n:type factoryConfigPath: string\n:rtype: linphone.Core"), - HandWrittenClassMethod('Core', 'new_with_config', 'linphone_core_new_with_config', "Instantiate a LinphoneCore object from a LpConfig.\n\n:param vtable: The callbacks.\n:type vtable: dictionary\n:param config: A LpConfig object holding the configuration of the LinphoneCore to be instantiated.\n:rtype: linphone.Core") + HandWrittenClassMethod('Core', 'new_with_config', 'linphone_core_new_with_config', "Instantiate a LinphoneCore object from a LpConfig.\n\n:param vtable: The callbacks.\n:type vtable: dictionary\n:param config: A LpConfig object holding the configuration of the LinphoneCore to be instantiated.\n:rtype: linphone.Core"), + HandWrittenDeallocMethod('Core', 'linphone_core_destroy') ] def generate(apixmlfile, outputfile): diff --git a/tools/python/apixml2python/handwritten_declarations.mustache b/tools/python/apixml2python/handwritten_declarations.mustache index 3fcb43c2b..4a4b2c1ef 100644 --- a/tools/python/apixml2python/handwritten_declarations.mustache +++ b/tools/python/apixml2python/handwritten_declarations.mustache @@ -1,5 +1,6 @@ static PyObject * pylinphone_Core_get_sip_transports(PyObject *self, void *closure); static int pylinphone_Core_set_sip_transports(PyObject *self, PyObject *value, void *closure); +static void pylinphone_Core_dealloc(PyObject *self); static PyObject * pylinphone_Core_get_sip_transports_used(PyObject *self, void *closure); static PyObject * pylinphone_Core_get_sound_devices(PyObject *self, void *closure); static PyObject * pylinphone_Core_get_video_devices(PyObject *self, void *closure); diff --git a/tools/python/apixml2python/handwritten_definitions.mustache b/tools/python/apixml2python/handwritten_definitions.mustache index d3bd0cbdb..13e27d873 100644 --- a/tools/python/apixml2python/handwritten_definitions.mustache +++ b/tools/python/apixml2python/handwritten_definitions.mustache @@ -336,6 +336,24 @@ static PyObject * pylinphone_Core_class_method_new_with_config(PyObject *cls, Py return pyret; } +static void pylinphone_Core_dealloc(PyObject *self) { + LinphoneCore * native_ptr = pylinphone_Core_get_native_ptr(self); + if (Py_REFCNT(self) < 0) return; + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p [%p])", __FUNCTION__, self, native_ptr); + + if (native_ptr != NULL) { + linphone_core_destroy(native_ptr); + ms_exit(); // De-initialize mediastreamer + } + + pylinphone_dispatch_messages(); + Py_XDECREF(((pylinphone_CoreObject *)self)->user_data); + Py_XDECREF(((pylinphone_CoreObject *)self)->vtable_dict); + + self->ob_type->tp_free(self); + pylinphone_trace(-1, "[PYLINPHONE] <<< %s", __FUNCTION__); +} + static void pylinphone_VideoSize_dealloc(PyObject *self) { diff --git a/tools/python/apixml2python/linphone.py b/tools/python/apixml2python/linphone.py index a4f6f8a2d..16d726850 100644 --- a/tools/python/apixml2python/linphone.py +++ b/tools/python/apixml2python/linphone.py @@ -69,6 +69,10 @@ class HandWrittenClassMethod(HandWrittenCode): def __init__(self, _class, name, cfunction, doc = ''): HandWrittenCode.__init__(self, _class, name, [cfunction], doc) +class HandWrittenDeallocMethod(HandWrittenCode): + def __init__(self, _class, cfunction): + HandWrittenCode.__init__(self, _class, 'dealloc', [cfunction], '') + class HandWrittenProperty(HandWrittenCode): def __init__(self, _class, name, getter_cfunction = None, setter_cfunction = None, doc = ''): func_list = [] @@ -698,6 +702,12 @@ class DeallocMethodDefinition(MethodDefinition): def format_return_result(self): return '' + def format(self): + return \ +"""static void pylinphone_{class_name}_dealloc(PyObject *self) {{ +{method_body} +}}""".format(class_name=self.class_['class_name'], method_body=MethodDefinition.format(self)) + class GetterMethodDefinition(MethodDefinition): def __init__(self, linphone_module, class_, method_node = None): MethodDefinition.__init__(self, linphone_module, class_, method_node) @@ -1069,6 +1079,8 @@ class LinphoneModule(object): m['method_name'] = hand_written_code.name m['method_doc'] = self.__replace_doc_special_chars(hand_written_code.doc) c['class_instance_hand_written_methods'].append(m) + elif isinstance(hand_written_code, HandWrittenDeallocMethod): + c['class_has_hand_written_dealloc'] = True elif isinstance(hand_written_code, HandWrittenProperty): p = {} p['property_name'] = hand_written_code.name @@ -1199,18 +1211,19 @@ class LinphoneModule(object): except Exception, e: e.args += (c['class_name'], p['property_name']) raise - try: - if c['class_refcountable']: - xml_instance_method = c['class_xml_node'].find("./instancemethods/instancemethod[@name='" + c['class_c_function_prefix'] + "unref']") - c['dealloc_body'] = DeallocMethodDefinition(self, c, xml_instance_method).format() - elif c['class_destroyable']: - xml_instance_method = c['class_xml_node'].find("./instancemethods/instancemethod[@name='" + c['class_c_function_prefix'] + "destroy']") - c['dealloc_body'] = DeallocMethodDefinition(self, c, xml_instance_method).format() - else: - c['dealloc_body'] = DeallocMethodDefinition(self, c).format() - except Exception, e: - e.args += (c['class_name'], 'dealloc_body') - raise + if not 'class_has_hand_written_dealloc' in c: + try: + if c['class_refcountable']: + xml_instance_method = c['class_xml_node'].find("./instancemethods/instancemethod[@name='" + c['class_c_function_prefix'] + "unref']") + c['dealloc_definition'] = DeallocMethodDefinition(self, c, xml_instance_method).format() + elif c['class_destroyable']: + xml_instance_method = c['class_xml_node'].find("./instancemethods/instancemethod[@name='" + c['class_c_function_prefix'] + "destroy']") + c['dealloc_definition'] = DeallocMethodDefinition(self, c, xml_instance_method).format() + else: + c['dealloc_definition'] = DeallocMethodDefinition(self, c).format() + except Exception, e: + e.args += (c['class_name'], 'dealloc_body') + raise # Convert mslist_types to a list of dictionaries for the template d = [] for mslist_type in self.mslist_types: diff --git a/tools/python/apixml2python/linphone_module.mustache b/tools/python/apixml2python/linphone_module.mustache index 000b16a8a..403a2491a 100644 --- a/tools/python/apixml2python/linphone_module.mustache +++ b/tools/python/apixml2python/linphone_module.mustache @@ -125,9 +125,7 @@ static int pylinphone_{{class_name}}_init(PyObject *self, PyObject *args, PyObje {{{init_body}}} } -static void pylinphone_{{class_name}}_dealloc(PyObject *self) { -{{{dealloc_body}}} -} +{{{dealloc_definition}}} {{#class_type_methods}}