Commit 4a335ba6 authored by Ghislain MARY's avatar Ghislain MARY
Browse files

Complete handling of time_t type in the Python wrapper.

parent 719b507b
......@@ -46,7 +46,6 @@ blacklisted_functions = [
'linphone_chat_message_start_file_download', # to be handwritten because of callback
'linphone_chat_message_state_to_string', # There is no use to wrap this function
'linphone_chat_room_create_file_transfer_message', # missing LinphoneContent
'linphone_chat_room_create_message_2', # missing time_t
'linphone_core_can_we_add_call', # private function
'linphone_core_get_audio_port_range', # to be handwritten because of result via arguments
'linphone_core_get_default_proxy', # to be handwritten because of double pointer indirection
......
......@@ -394,12 +394,28 @@ PyObject * PyLinphoneVideoSize_FromMSVideoSize(MSVideoSize vs) {
time_t PyDateTime_As_time_t(PyObject *obj) {
time_t ret = -1;
PyObject *utctimetuple = PyObject_GetAttrString(obj, "utctimetuple");
if (utctimetuple != NULL) {
PyObject *calendar_module = PyImport_ImportModule("calendar");
if (calendar_module != NULL) {
PyObject *timegm = PyObject_GetAttrString(calendar_module, "timegm");
if (timegm != NULL) {
PyObject *tuple = PyEval_CallObject(utctimetuple, Py_BuildValue("()"));
PyObject *pyres = PyEval_CallObject(timegm, Py_BuildValue("(O)", tuple));
ret = (time_t)PyLong_AsLong(pyres);
Py_DECREF(timegm);
}
Py_DECREF(calendar_module);
}
Py_DECREF(utctimetuple);
}
return ret;
}
PyObject * PyDateTime_From_time_t(time_t t) {
PyObject *pyret = NULL;
PyObject *datetime_module;
PyObject *datetime_class;
if (t == -1) {
Py_RETURN_NONE;
}
......
......@@ -50,6 +50,7 @@ class ArgumentType:
self.convert_from_func = None
self.fmt_str = 'O'
self.cfmt_str = '%p'
self.cnativefmt_str = '%p'
self.use_native_pointer = False
self.cast_convert_func_result = True
self.__compute()
......@@ -146,6 +147,7 @@ class ArgumentType:
self.convert_from_func = 'PyDateTime_From_time_t'
self.fmt_str = 'O'
self.cfmt_str = '%p'
self.cnativefmt_str = "%ld"
elif self.basic_type == 'MSList':
self.type_str = 'list of linphone.' + self.contained_type
self.check_func = 'PyList_Check'
......@@ -214,9 +216,12 @@ class MethodDefinition:
arg_contained_type = xml_method_arg.get('containedtype')
argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module)
self.parse_tuple_format += argument_type.fmt_str
if argument_type.use_native_pointer:
if argument_type.fmt_str == 'O' and argument_type.use_native_pointer:
body += "\tPyObject * " + arg_name + ";\n"
body += "\t" + arg_complete_type + " " + arg_name + "_native_ptr = NULL;\n"
elif argument_type.fmt_str == 'O' and argument_type.convert_func is not None:
body += "\tPyObject * " + arg_name + ";\n"
body += "\t" + arg_complete_type + " " + arg_name + "_native_obj;\n"
elif strip_leading_linphone(arg_complete_type) in self.linphone_module.enum_names:
body += "\tint " + arg_name + ";\n"
else:
......@@ -235,15 +240,28 @@ class MethodDefinition:
return NULL;
}}
""".format(fmt=self.parse_tuple_format, args=', '.join(map(lambda a: '&' + a, self.arg_names)))
args_conversion_code = ''
for xml_method_arg in self.xml_method_args:
arg_name = "_" + xml_method_arg.get('name')
arg_type = xml_method_arg.get('type')
arg_complete_type = xml_method_arg.get('completetype')
arg_contained_type = xml_method_arg.get('containedtype')
argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module)
if argument_type.fmt_str == 'O' and argument_type.convert_func is not None:
args_conversion_code += \
""" {arg_name}_native_obj = {convert_func}({arg_name});
""".format(arg_name=arg_name, convert_func=argument_type.convert_func)
return \
""" {class_native_ptr_check_code}
{parse_tuple_code}
{args_type_check_code}
{args_native_ptr_check_code}
{args_conversion_code}
""".format(class_native_ptr_check_code=class_native_ptr_check_code,
parse_tuple_code=parse_tuple_code,
args_type_check_code=self.format_args_type_check(),
args_native_ptr_check_code=self.format_args_native_pointer_check())
args_native_ptr_check_code=self.format_args_native_pointer_check(),
args_conversion_code=args_conversion_code)
def format_enter_trace(self):
fmt = ''
......@@ -262,8 +280,11 @@ class MethodDefinition:
fmt += argument_type.cfmt_str
args.append(arg_name)
if argument_type.fmt_str == 'O':
fmt += ' [' + argument_type.cfmt_str + ']'
args.append(arg_name)
fmt += ' [' + argument_type.cnativefmt_str + ']'
if argument_type.use_native_pointer:
args.append(arg_name + '_native_ptr')
else:
args.append(arg_name + '_native_obj')
args = ', '.join(args)
if args != '':
args = ', ' + args
......@@ -278,8 +299,10 @@ class MethodDefinition:
arg_complete_type = xml_method_arg.get('completetype')
arg_contained_type = xml_method_arg.get('containedtype')
argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module)
if argument_type.convert_func is None:
if argument_type.fmt_str == 'O' and argument_type.use_native_pointer:
arg_names.append(arg_name + "_native_ptr")
elif argument_type.fmt_str == 'O' and argument_type.convert_func is not None:
arg_names.append(arg_name + "_native_obj")
else:
arg_names.append(arg_name)
if self.return_type != 'void':
......@@ -383,13 +406,22 @@ class MethodDefinition:
arg_contained_type = xml_method_arg.get('containedtype')
argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module)
if argument_type.fmt_str == 'O':
body += \
if argument_type.use_native_pointer:
body += \
""" if (({arg_name} != Py_None) && !PyObject_IsInstance({arg_name}, (PyObject *)&pylinphone_{arg_type}Type)) {{
PyErr_SetString(PyExc_TypeError, "The '{arg_name}' arguments must be a {type_str} instance.");
PyErr_SetString(PyExc_TypeError, "The '{arg_name}' argument must be a {type_str} instance.");
return NULL;
}}
""".format(arg_name=arg_name, arg_type=strip_leading_linphone(arg_type), type_str=argument_type.type_str)
body = body[1:] # Remove leading '\t'
else:
body += \
""" if (!{check_func}({arg_name})) {{
PyErr_SetString(PyExc_TypeError, "The '{arg_name}' argument must be a {type_str} instance.");
return NULL;
}}
""".format(arg_name=arg_name, check_func=argument_type.check_func, type_str=argument_type.type_str)
if body != '':
body = body[1:] # Remove leading '\t'
return body
def format_args_native_pointer_check(self):
......@@ -400,7 +432,7 @@ class MethodDefinition:
arg_complete_type = xml_method_arg.get('completetype')
arg_contained_type = xml_method_arg.get('containedtype')
argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module)
if argument_type.fmt_str == 'O':
if argument_type.fmt_str == 'O' and argument_type.use_native_pointer:
body += \
""" if (({arg_name} != NULL) && ({arg_name} != Py_None)) {{
if (({arg_name}_native_ptr = pylinphone_{arg_type}_get_native_ptr({arg_name})) == NULL) {{
......@@ -408,7 +440,8 @@ class MethodDefinition:
}}
}}
""".format(arg_name=arg_name, arg_type=strip_leading_linphone(arg_type))
body = body[1:] # Remove leading '\t'
if body != '':
body = body[1:] # Remove leading '\t'
return body
def parse_method_node(self):
......@@ -572,14 +605,19 @@ class SetterMethodDefinition(MethodDefinition):
return -1;
}}
""".format(checknotnone=checknotnone, checkfunc=self.first_argument_type.check_func, attribute_name=self.attribute_name, type_str=self.first_argument_type.type_str)
if self.first_argument_type.convert_func is None:
attribute_conversion_code = "{arg_name} = value;\n".format(arg_name="_" + self.first_arg_name)
else:
attribute_conversion_code = ''
if (self.first_argument_type.convert_func is None) or \
(self.first_argument_type.fmt_str == 'O' and self.first_argument_type.convert_func is not None):
attribute_conversion_code += "{arg_name} = value;\n".format(arg_name="_" + self.first_arg_name)
if self.first_argument_type.convert_func is not None:
cast_code = ''
suffix = ''
if self.first_argument_type.cast_convert_func_result:
cast_code = "({arg_type})".format(arg_type=self.first_arg_complete_type)
attribute_conversion_code = "{arg_name} = {cast_code}{convertfunc}(value);\n".format(
arg_name="_" + self.first_arg_name, cast_code=cast_code, convertfunc=self.first_argument_type.convert_func)
if self.first_argument_type.fmt_str == 'O' and self.first_argument_type.convert_func is not None:
suffix = '_native_obj'
attribute_conversion_code += "\t{arg_name}{suffix} = {cast_code}{convertfunc}(value);\n".format(
arg_name="_" + self.first_arg_name, suffix=suffix, cast_code=cast_code, convertfunc=self.first_argument_type.convert_func)
attribute_native_ptr_check_code = ''
if self.first_argument_type.use_native_pointer:
attribute_native_ptr_check_code = \
......@@ -606,13 +644,15 @@ class SetterMethodDefinition(MethodDefinition):
attribute_native_ptr_check_code=attribute_native_ptr_check_code)
def format_c_function_call(self):
use_native_ptr = ''
if self.first_argument_type.use_native_pointer:
use_native_ptr = '_native_ptr'
suffix = ''
if self.first_argument_type.fmt_str == 'O' and self.first_argument_type.use_native_pointer:
suffix = '_native_ptr'
elif self.first_argument_type.fmt_str == 'O' and self.first_argument_type.convert_func is not None:
suffix = '_native_obj'
return \
""" {method_name}(native_ptr, {arg_name}{use_native_ptr});
""" {method_name}(native_ptr, {arg_name}{suffix});
pylinphone_dispatch_messages();
""".format(arg_name="_" + self.first_arg_name, method_name=self.method_node.get('name'), use_native_ptr=use_native_ptr)
""".format(arg_name="_" + self.first_arg_name, method_name=self.method_node.get('name'), suffix=suffix)
def format_return_trace(self):
return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s -> 0\", __FUNCTION__);\n"
......
......@@ -18,6 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <Python.h>
#include <structmember.h>
#include <datetime.h>
#include <linphone/linphonecore.h>
#include <linphone/linphone_tunnel.h>
#include <linphone/linphonecore_utils.h>
......@@ -265,6 +266,7 @@ PyMODINIT_FUNC initlinphone(void) {
PyObject *m;
PyObject *menum;
PyDateTime_IMPORT;
pylinphone_init_logging();
{{#classes}}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment