forked from mirrors/linphone-iphone
Improve Python reference counting.
This commit is contained in:
parent
2150ce6f5c
commit
d23934feab
3 changed files with 56 additions and 50 deletions
|
|
@ -259,18 +259,16 @@ static PyObject * pylinphone_Core_class_method_new_with_config(PyObject *cls, Py
|
|||
static void pylinphone_ChatRoom_callback_chat_message_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageState state, void *ud) {
|
||||
PyGILState_STATE pygil_state;
|
||||
PyObject *pycm = NULL;
|
||||
bool_t incref = FALSE;
|
||||
PyObject *_dict = (PyObject *)ud;
|
||||
PyObject *_cb = PyDict_GetItemString(_dict, "callback");
|
||||
PyObject *_ud = PyDict_GetItemString(_dict, "user_data");
|
||||
|
||||
pygil_state = PyGILState_Ensure();
|
||||
pycm = linphone_chat_message_get_user_data(msg);
|
||||
if (pycm == NULL) {
|
||||
pycm = pylinphone_ChatMessage_new_from_native_ptr(&pylinphone_ChatMessageType, msg);
|
||||
}
|
||||
pycm = pylinphone_ChatMessage_from_native_ptr(&pylinphone_ChatMessageType, msg, &incref);
|
||||
pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p, %p [%p], %d, %p)", __FUNCTION__, pycm, msg, state, ud);
|
||||
if ((_cb != NULL) && PyCallable_Check(_cb)) {
|
||||
if (PyEval_CallObject(_cb, Py_BuildValue("OiO", pycm, state, _ud)) == NULL) {
|
||||
if (PyEval_CallObject(_cb, Py_BuildValue((incref == TRUE) ? "OiO" : "NiO", pycm, state, _ud)) == NULL) {
|
||||
PyErr_Print();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -208,7 +208,9 @@ class MethodDefinition:
|
|||
self.build_value_format = argument_type.fmt_str
|
||||
if self.build_value_format == 'O':
|
||||
body += "\tPyObject * pyresult;\n"
|
||||
body += "\tbool_t incref = FALSE;\n"
|
||||
body += "\tPyObject * pyret;\n"
|
||||
body += "\tconst char *pyret_fmt;\n"
|
||||
if self.self_arg is not None:
|
||||
body += "\t" + self.self_arg.get('completetype') + "native_ptr;\n"
|
||||
for xml_method_arg in self.xml_method_args:
|
||||
|
|
@ -315,9 +317,9 @@ class MethodDefinition:
|
|||
if len(arg_names) > 0:
|
||||
c_function_call_code += ', '
|
||||
c_function_call_code += ', '.join(arg_names) + ");"
|
||||
return_from_user_data_code = ''
|
||||
new_from_native_pointer_code = ''
|
||||
from_native_pointer_code = ''
|
||||
convert_from_code = ''
|
||||
pyret_fmt_fill_code = ''
|
||||
build_value_code = ''
|
||||
result_variable = ''
|
||||
if self.return_complete_type != 'void':
|
||||
|
|
@ -325,36 +327,31 @@ class MethodDefinition:
|
|||
stripped_return_type = strip_leading_linphone(self.return_type)
|
||||
return_type_class = self.find_class_definition(self.return_type)
|
||||
if return_type_class is not None:
|
||||
if return_type_class['class_has_user_data']:
|
||||
get_user_data_function = return_type_class['class_c_function_prefix'] + "get_user_data"
|
||||
return_from_user_data_code = \
|
||||
"""if ((cresult != NULL) && ({func}(cresult) != NULL)) {{
|
||||
return Py_BuildValue("O", (PyObject *){func}(cresult));
|
||||
}}
|
||||
""".format(func=get_user_data_function)
|
||||
new_from_native_pointer_code = "pyresult = pylinphone_{return_type}_new_from_native_ptr(&pylinphone_{return_type}Type, cresult);\n".format(return_type=stripped_return_type)
|
||||
from_native_pointer_code = "pyresult = pylinphone_{return_type}_from_native_ptr(&pylinphone_{return_type}Type, cresult, &incref);\n".format(return_type=stripped_return_type)
|
||||
else:
|
||||
return_argument_type = ArgumentType(self.return_type, self.return_complete_type, self.return_contained_type, self.linphone_module)
|
||||
if return_argument_type.convert_from_func is not None:
|
||||
convert_from_code = \
|
||||
"""pyresult = {convert_func}(cresult);
|
||||
""".format(convert_func=return_argument_type.convert_from_func)
|
||||
pyret_fmt_fill_code = "pyret_fmt = (incref == TRUE) ? \"O\" : \"N\";"
|
||||
result_variable = 'pyresult'
|
||||
else:
|
||||
pyret_fmt_fill_code = "pyret_fmt = \"{fmt}\";\n".format(fmt=self.build_value_format)
|
||||
result_variable = 'cresult'
|
||||
if result_variable != '':
|
||||
build_value_code = "pyret = Py_BuildValue(\"{fmt}\", {result_variable});\n".format(fmt=self.build_value_format.replace('O', 'N'), result_variable=result_variable)
|
||||
build_value_code = "pyret = Py_BuildValue(pyret_fmt, {result_variable});".format(fmt=self.build_value_format.replace('O', 'N'), result_variable=result_variable)
|
||||
body = \
|
||||
""" {c_function_call_code}
|
||||
pylinphone_dispatch_messages();
|
||||
{return_from_user_data_code}
|
||||
{new_from_native_pointer_code}
|
||||
{from_native_pointer_code}
|
||||
{convert_from_code}
|
||||
{pyret_fmt_fill_code}
|
||||
{build_value_code}
|
||||
""".format(c_function_call_code=c_function_call_code,
|
||||
return_from_user_data_code=return_from_user_data_code,
|
||||
new_from_native_pointer_code=new_from_native_pointer_code,
|
||||
from_native_pointer_code=from_native_pointer_code,
|
||||
convert_from_code=convert_from_code,
|
||||
pyret_fmt_fill_code=pyret_fmt_fill_code,
|
||||
build_value_code=build_value_code)
|
||||
return body
|
||||
|
||||
|
|
@ -510,12 +507,12 @@ class InitMethodDefinition(MethodDefinition):
|
|||
def format_return_result(self):
|
||||
return "\treturn 0;"
|
||||
|
||||
class NewFromNativePointerMethodDefinition(MethodDefinition):
|
||||
class FromNativePointerMethodDefinition(MethodDefinition):
|
||||
def __init__(self, linphone_module, class_):
|
||||
MethodDefinition.__init__(self, linphone_module, class_, None)
|
||||
|
||||
def format_local_variables_definition(self):
|
||||
return "\tpylinphone_{class_name}Object *self;\n".format(class_name=self.class_['class_name'])
|
||||
return "\tpylinphone_{class_name}Object *self = NULL;\n".format(class_name=self.class_['class_name'])
|
||||
|
||||
def format_arguments_parsing(self):
|
||||
return ''
|
||||
|
|
@ -524,28 +521,38 @@ class NewFromNativePointerMethodDefinition(MethodDefinition):
|
|||
return "\tpylinphone_trace(1, \"[PYLINPHONE] >>> %s(%p)\", __FUNCTION__, native_ptr);\n"
|
||||
|
||||
def format_c_function_call(self):
|
||||
get_user_data_func_call = ''
|
||||
set_user_data_func_call = ''
|
||||
incref_code = ''
|
||||
if self.class_['class_has_user_data']:
|
||||
get_user_data_func_call = "self = (pylinphone_{class_name}Object *){function_prefix}get_user_data(native_ptr);".format(class_name=self.class_['class_name'], function_prefix=self.class_['class_c_function_prefix'])
|
||||
set_user_data_func_call = "{function_prefix}set_user_data(self->native_ptr, self);".format(function_prefix=self.class_['class_c_function_prefix'])
|
||||
incref_code = "*incref = TRUE;"
|
||||
ref_native_pointer_code = ''
|
||||
if self.class_['class_refcountable']:
|
||||
ref_native_pointer_code = "{func}(self->native_ptr);".format(func=self.class_['class_c_function_prefix'] + "ref")
|
||||
return \
|
||||
""" if (native_ptr == NULL) {{
|
||||
""" *incref = FALSE;
|
||||
if (native_ptr == NULL) {{
|
||||
{none_trace}
|
||||
Py_RETURN_NONE;
|
||||
}}
|
||||
self = (pylinphone_{class_name}Object *)PyObject_CallObject((PyObject *)&pylinphone_{class_name}Type, NULL);
|
||||
{get_user_data_func_call}
|
||||
if (self == NULL) {{
|
||||
{none_trace}
|
||||
Py_RETURN_NONE;
|
||||
self = (pylinphone_{class_name}Object *)PyObject_CallObject((PyObject *)&pylinphone_{class_name}Type, NULL);
|
||||
if (self == NULL) {{
|
||||
{none_trace}
|
||||
Py_RETURN_NONE;
|
||||
}}
|
||||
self->native_ptr = ({class_cname} *)native_ptr;
|
||||
{set_user_data_func_call}
|
||||
{ref_native_pointer_code}
|
||||
}}
|
||||
self->native_ptr = ({class_cname} *)native_ptr;
|
||||
{set_user_data_func_call}
|
||||
{ref_native_pointer_code}
|
||||
{incref_code}
|
||||
""".format(class_name=self.class_['class_name'], class_cname=self.class_['class_cname'],
|
||||
none_trace=self.format_return_none_trace(), set_user_data_func_call=set_user_data_func_call,
|
||||
ref_native_pointer_code=ref_native_pointer_code)
|
||||
none_trace=self.format_return_none_trace(),
|
||||
get_user_data_func_call=get_user_data_func_call, set_user_data_func_call=set_user_data_func_call,
|
||||
ref_native_pointer_code=ref_native_pointer_code, incref_code=incref_code)
|
||||
|
||||
def format_return_trace(self):
|
||||
return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s -> %p\", __FUNCTION__, self);\n"
|
||||
|
|
@ -710,13 +717,14 @@ class EventCallbackMethodDefinition(MethodDefinition):
|
|||
PyGILState_STATE pygil_state;""".format(name=self.class_['event_name'])
|
||||
specific = ''
|
||||
for xml_method_arg in self.xml_method_args:
|
||||
arg_name = 'py' + xml_method_arg.get('name')
|
||||
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':
|
||||
specific += "\tPyObject * " + arg_name + " = NULL;\n"
|
||||
specific += "\tPyObject * py" + arg_name + " = NULL;\n"
|
||||
specific += "\tbool_t incref_" + arg_name + " = FALSE;\n"
|
||||
return "{common}\n{specific}".format(common=common, specific=specific)
|
||||
|
||||
def format_arguments_parsing(self):
|
||||
|
|
@ -741,7 +749,7 @@ class EventCallbackMethodDefinition(MethodDefinition):
|
|||
return "\tpylinphone_trace(1, \"[PYLINPHONE] >>> %s({fmt})\", __FUNCTION__{args});\n".format(fmt=fmt, args=args)
|
||||
|
||||
def format_c_function_call(self):
|
||||
create_python_objects_code = ''
|
||||
create_python_objects_code = "\t\tPy_INCREF(pylc);\n"
|
||||
decref_python_objects_code = ''
|
||||
fmt = 'O'
|
||||
args = ['pylc']
|
||||
|
|
@ -761,20 +769,16 @@ class EventCallbackMethodDefinition(MethodDefinition):
|
|||
create_python_objects_code += "\t\tpy{name} = {convert_from_func}({name});\n".format(name=arg_name, convert_from_func=argument_type.convert_from_func)
|
||||
else:
|
||||
type_class = self.find_class_definition(arg_type)
|
||||
get_user_data_code = ''
|
||||
new_from_native_pointer_code = "py{name} = pylinphone_{arg_type}_new_from_native_ptr(&pylinphone_{arg_type}Type, {name});".format(name=arg_name, arg_type=strip_leading_linphone(arg_type))
|
||||
from_native_pointer_code = "py{name} = pylinphone_{arg_type}_from_native_ptr(&pylinphone_{arg_type}Type, {name}, &incref_{name});".format(name=arg_name, arg_type=strip_leading_linphone(arg_type))
|
||||
if type_class is not None and type_class['class_has_user_data']:
|
||||
get_user_data_function = type_class['class_c_function_prefix'] + "get_user_data"
|
||||
get_user_data_code = "py{name} = {get_user_data_function}({name});".format(name=arg_name, get_user_data_function=get_user_data_function)
|
||||
create_python_objects_code += \
|
||||
""" {get_user_data_code}
|
||||
if (py{name} == NULL) {{
|
||||
{new_from_native_pointer_code}
|
||||
}}
|
||||
Py_INCREF(py{name});
|
||||
""".format(name=arg_name, get_user_data_code=get_user_data_code, new_from_native_pointer_code=new_from_native_pointer_code)
|
||||
decref_python_objects_code += "\t\tPy_DECREF(py{name});\n".format(name=arg_name)
|
||||
""" {from_native_pointer_code}
|
||||
if (incref_{name} == TRUE) Py_INCREF(py{name});
|
||||
""".format(name=arg_name, from_native_pointer_code=from_native_pointer_code)
|
||||
decref_python_objects_code += "\t\tif (incref_{name} == TRUE) Py_DECREF(py{name});\n".format(name=arg_name)
|
||||
args=', '.join(args)
|
||||
decref_python_objects_code += "\t\tPy_DECREF(pylc);"
|
||||
return \
|
||||
""" if ((func != NULL) && PyCallable_Check(func)) {{
|
||||
{create_python_objects_code}
|
||||
|
|
@ -973,9 +977,9 @@ class LinphoneModule(object):
|
|||
e.args += (c['class_name'], 'init_body')
|
||||
raise
|
||||
try:
|
||||
c['new_from_native_pointer_body'] = NewFromNativePointerMethodDefinition(self, c).format()
|
||||
c['from_native_pointer_body'] = FromNativePointerMethodDefinition(self, c).format()
|
||||
except Exception, e:
|
||||
e.args += (c['class_name'], 'new_from_native_pointer_body')
|
||||
e.args += (c['class_name'], 'from_native_pointer_body')
|
||||
raise
|
||||
try:
|
||||
for m in c['class_type_methods']:
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ typedef struct {
|
|||
|
||||
{{#classes}}
|
||||
static {{class_cname}} * pylinphone_{{class_name}}_get_native_ptr(PyObject *self);
|
||||
static PyObject * pylinphone_{{class_name}}_new_from_native_ptr(PyTypeObject *type, const {{class_cname}} *native_ptr);
|
||||
static PyObject * pylinphone_{{class_name}}_from_native_ptr(PyTypeObject *type, const {{class_cname}} *native_ptr, bool_t *incref);
|
||||
{{#class_type_hand_written_methods}}
|
||||
static PyObject * pylinphone_{{class_name}}_class_method_{{method_name}}(PyObject *cls, PyObject *args);
|
||||
{{/class_type_hand_written_methods}}
|
||||
|
|
@ -75,9 +75,13 @@ static PyObject * pylinphone_{{class_name}}_instance_method_{{method_name}}(PyOb
|
|||
PyObject * PyList_FromMSListOf{{c_contained_type}}(const MSList *msl) {
|
||||
PyObject *pyl = PyList_New(0);
|
||||
while (msl != NULL) {
|
||||
bool_t incref = FALSE;
|
||||
{{c_contained_type}} *native_ptr = ({{c_contained_type}} *)msl->data;
|
||||
PyObject *item = pylinphone_{{python_contained_type}}_new_from_native_ptr(&pylinphone_{{python_contained_type}}Type, native_ptr);
|
||||
PyObject *item = pylinphone_{{python_contained_type}}_from_native_ptr(&pylinphone_{{python_contained_type}}Type, native_ptr, &incref);
|
||||
PyList_Append(pyl, item);
|
||||
if (incref != TRUE) {
|
||||
Py_DECREF(item);
|
||||
}
|
||||
msl = ms_list_next(msl);
|
||||
}
|
||||
return pyl;
|
||||
|
|
@ -107,8 +111,8 @@ static {{class_cname}} * pylinphone_{{class_name}}_get_native_ptr(PyObject *self
|
|||
return ((pylinphone_{{class_name}}Object *)self)->native_ptr;
|
||||
}
|
||||
|
||||
static PyObject * pylinphone_{{class_name}}_new_from_native_ptr(PyTypeObject *type, const {{class_cname}} *native_ptr) {
|
||||
{{{new_from_native_pointer_body}}}
|
||||
static PyObject * pylinphone_{{class_name}}_from_native_ptr(PyTypeObject *type, const {{class_cname}} *native_ptr, bool_t *incref) {
|
||||
{{{from_native_pointer_body}}}
|
||||
}
|
||||
|
||||
static PyObject * pylinphone_{{class_name}}_new(PyTypeObject *type, PyObject *args, PyObject *kw) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue