From a8565b049bd8ec82d5a44f804466099f25ac899b Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Wed, 9 Jul 2014 10:23:28 +0200 Subject: [PATCH] Handle creation of Python object from native object pointer. --- tools/python/apixml2python/linphone.py | 33 +++++++++++++++---- .../apixml2python/linphone_module.mustache | 16 +++++++++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/tools/python/apixml2python/linphone.py b/tools/python/apixml2python/linphone.py index 63534f60f..7c5146da4 100644 --- a/tools/python/apixml2python/linphone.py +++ b/tools/python/apixml2python/linphone.py @@ -25,7 +25,7 @@ class LinphoneModule(object): for xml_type_method in xml_type_methods: m = {} m['method_name'] = xml_type_method.get('name').replace(c['class_c_function_prefix'], '') - m['method_body'] = self.__format_method_body(xml_type_method) + m['method_body'] = self.__format_method_body(xml_type_method, c['class_name']) c['class_type_methods'].append(m) c['class_instance_methods'] = [] xml_instance_methods = xml_class.findall("./instancemethods/instancemethod") @@ -47,7 +47,7 @@ class LinphoneModule(object): c['class_properties'].append(p) self.classes.append(c) - def __ctype_to_parse_tuple_format(self, ctype): + def __ctype_to_python_format(self, ctype): keywords = ['const', 'struct', 'enum', 'signed', 'unsigned', 'short', 'long', '*'] splitted_type = ctype.split(' ') for s in splitted_type: @@ -87,21 +87,42 @@ class LinphoneModule(object): else: return 'O' - def __format_method_body(self, method_node): + def __format_method_body(self, method_node, class_name): body = '' parse_tuple_format = '' + xml_method_return = method_node.find('./return') + return_type = xml_method_return.get('type') + if return_type != 'void': + body += "\t" + return_type + " cresult;\n" + build_value_format = self.__ctype_to_python_format(return_type) + if build_value_format == 'O': + body += "\tPyObject * pyresult;\n" + body += "\tPyObject * pyret;\n" xml_method_args = method_node.findall('./arguments/argument') arg_names = [] for xml_method_arg in xml_method_args: - parse_tuple_format += self.__ctype_to_parse_tuple_format(xml_method_arg.get('type')) + parse_tuple_format += self.__ctype_to_python_format(xml_method_arg.get('type')) body += "\t" + xml_method_arg.get('type') + " " + xml_method_arg.get('name') + ";\n" arg_names.append(xml_method_arg.get('name')) - body += "\tpylinphone_trace(__FUNCTION__);\n" if len(xml_method_args) > 0: body += "\n\tif (!PyArg_ParseTuple(args, \"" + parse_tuple_format + "\"" body += ', ' + ', '.join(map(lambda a: '&' + a, arg_names)) body += ")) {\n\t\treturn NULL;\n\t}\n\n" - body += "\tPy_RETURN_NONE;" + body += "\tpylinphone_trace(__FUNCTION__);\n\n" + body += "\t" + if return_type != 'void': + body += "cresult = " + body += method_node.get('name') + "(" + ', '.join(arg_names) + ");\n" + if return_type != 'void': + if build_value_format == 'O': + body += "\tpyresult = pylinphone_" + class_name + "_new_from_native_ptr(&pylinphone_" + class_name + "Type, cresult);\n" + body += "\tpyret = Py_BuildValue(\"" + build_value_format + "\", pyresult);\n" + body += "\tPy_DECREF(pyresult);\n" + body += "\treturn pyret;" + else: + body += "\treturn Py_BuildValue(\"" + build_value_format + "\", cresult);" + else: + body += "\tPy_RETURN_NONE;" return body def __format_doc_node(self, node): diff --git a/tools/python/apixml2python/linphone_module.mustache b/tools/python/apixml2python/linphone_module.mustache index 7e4303a80..8b5a5b6eb 100644 --- a/tools/python/apixml2python/linphone_module.mustache +++ b/tools/python/apixml2python/linphone_module.mustache @@ -38,6 +38,12 @@ static void pylinphone_log(const char *level, const char *fmt) { #define pylinphone_trace pylinphone_debug +{{#classes}} + +static PyTypeObject pylinphone_{{class_name}}Type; + +{{/classes}} + {{#classes}} typedef struct { @@ -45,6 +51,16 @@ typedef struct { {{class_name}} *native_ptr; } pylinphone_{{class_name}}Object; +static PyObject * pylinphone_{{class_name}}_new_from_native_ptr(PyTypeObject *type, {{class_name}} *native_ptr) { + pylinphone_{{class_name}}Object *self; + pylinphone_trace(__FUNCTION__); + if (native_ptr == NULL) Py_RETURN_NONE; + self = (pylinphone_{{class_name}}Object *)PyObject_New(pylinphone_{{class_name}}Object, type); + if (self == NULL) Py_RETURN_NONE; + self->native_ptr = native_ptr; + return (PyObject *)self; +} + static PyObject * pylinphone_{{class_name}}_new(PyTypeObject *type, PyObject *args, PyObject *kw) { pylinphone_{{class_name}}Object *self = (pylinphone_{{class_name}}Object *)type->tp_alloc(type, 0); pylinphone_trace(__FUNCTION__);