kuuko pushed a commit to branch master.
commit 0f3c3999e35153c0790d75512ba4f666e591a66c
Author: Kai Huuhko <[email protected]>
Date: Tue Mar 26 18:53:13 2013 +0000
Make the conv functions more robust.
Now we may leak the strings from _(c)fruni which should be looked up
case by case. The positive side is that we no longer point to (possibly)
invalid memory.
Strings used with touni funcs are suspected to leak as well.
---
efl/elementary/window.pyx | 40 ++++++++--------
efl/eo/efl.eo.pyx | 113 ++++++++++++++++++++++++++++++++++------------
include/efl.eo.pxd | 10 ++--
3 files changed, 104 insertions(+), 59 deletions(-)
diff --git a/efl/elementary/window.pyx b/efl/elementary/window.pyx
index b2ba719..64b9dbd 100644
--- a/efl/elementary/window.pyx
+++ b/efl/elementary/window.pyx
@@ -221,7 +221,8 @@
include "widget_header.pxi"
-from libc.stdlib cimport free
+from libc.stdlib cimport malloc, free
+from libc.string cimport memcpy
from object cimport Object
@@ -756,31 +757,26 @@ cdef class Window(Object):
"""
def __set__(self, list profiles):
- cdef unsigned int count = len(profiles)
- elm_win_available_profiles_set(self.obj,
convert_python_list_strings_to_array_of_strings(profiles), count)
+ self.available_profiles_set(profiles)
def __get__(self):
- cdef:
- char **profiles
- unsigned int count
+ return self.available_profiles_get()
- ret = elm_win_available_profiles_get(self.obj, &profiles, &count)
- if ret is 0:
- raise RuntimeError("No available profiles")
-
- return convert_array_of_strings_to_python_list(profiles, count)
-
- def available_profiles_set(self, list profiles):
+ cpdef available_profiles_set(self, list profiles):
cdef:
- unsigned int count = len(profiles)
- const_char **lst =
convert_python_list_strings_to_array_of_strings(profiles)
-
- elm_win_available_profiles_set(self.obj, lst, count)
- for i in range(count):
- free(<void *>lst[i])
- free(lst)
-
- def available_profiles_get(self):
+ const_char **array
+ unsigned int arr_len = len(profiles)
+ unsigned int i
+
+ try:
+ array = convert_python_list_strings_to_array_of_strings(profiles)
+ elm_win_available_profiles_set(self.obj, array, arr_len)
+ finally:
+ for i in range(arr_len):
+ free(<void *>array[i])
+ free(array)
+
+ cpdef available_profiles_get(self):
cdef:
char **profiles
unsigned int count
diff --git a/efl/eo/efl.eo.pyx b/efl/eo/efl.eo.pyx
index fbc5814..1821ad3 100644
--- a/efl/eo/efl.eo.pyx
+++ b/efl/eo/efl.eo.pyx
@@ -17,6 +17,7 @@
from cpython cimport PyObject, Py_INCREF, Py_DECREF#, PyMem_Malloc, PyMem_Free
from libc.stdlib cimport malloc, free
+from libc.string cimport memcpy, strdup
from efl cimport Eina_Bool, const_Eina_List, eina_list_append, const_void
from efl.c_eo cimport Eo as cEo
from efl.c_eo cimport eo_init, eo_shutdown, eo_del, eo_unref, eo_wref_add,
eo_add, Eo_Class
@@ -37,46 +38,85 @@ cdef int PY_REFCOUNT(object o):
cdef unicode _touni(char* s):
+ """
+
+ Converts a char * to a python string object
+
+ Note: Remember to free the char * when it's no longer needed.
+
+ """
return s.decode('UTF-8', 'strict') if s else None
cdef unicode _ctouni(const_char *s):
+ """
+
+ Converts a const_char * to a python string object
+
+ Note: Remember to free the const_char * when it's no longer needed.
+
+ """
return s.decode('UTF-8', 'strict') if s else None
-cdef char *_fruni(s):
- cdef char *c_string
+cdef char *_fruni(object s):
+ """
+
+ Converts a python string object to a char *
+
+ Note: Remember to free the char * when it's no longer needed.
+
+ """
+ cdef:
+ char *c_string
+ str string
+ unicode unistr
+
if s is None:
return NULL
if isinstance(s, unicode):
- string = s.encode('UTF-8')
- # XXX: We lose reference here
- c_string = string
+ unistr = s
+ string = unistr.encode('UTF-8')
+ return strdup(string)
elif isinstance(s, str):
- c_string = s
- # XXX: Reference is lost unless the user keeps the string object around
+ return strdup(s)
else:
raise TypeError("Expected str or unicode object, got %s" %
(type(s).__name__))
- return c_string
-cdef const_char *_cfruni(s):
- cdef const_char *c_string
+cdef const_char *_cfruni(object s):
+ """
+
+ Converts a python string object to a const_char *
+
+ Note: Remember to free the const_char * when it's no longer needed.
+
+ """
+ cdef:
+ const_char *c_string
+ str string
+ unicode unistr
+
if s is None:
return NULL
if isinstance(s, unicode):
- string = s.encode('UTF-8')
- # XXX: We lose reference here
- c_string = string
+ unistr = s
+ string = unistr.encode('UTF-8')
+ return strdup(string)
elif isinstance(s, str):
- c_string = s
- # XXX: Reference is lost unless the user keeps the string object around
+ return strdup(s)
else:
raise TypeError("Expected str or unicode object, got %s" %
(type(s).__name__))
- return c_string
-cdef convert_array_of_strings_to_python_list(char **array, int array_length):
+cdef list convert_array_of_strings_to_python_list(char **array, int
array_length):
+ """
+
+ Converts an array of strings to a python list.
+
+ Note: Remember to free the array when it's no longer needed.
+
+ """
cdef char *string
ret = []
@@ -89,24 +129,37 @@ cdef convert_array_of_strings_to_python_list(char **array,
int array_length):
cdef const_char ** convert_python_list_strings_to_array_of_strings(list
strings):
+ """
+
+ Converts a python list to an array of strings.
+
+ Note: Remember to free the array when it's no longer needed.
+
+ """
cdef:
- const_char **lst
+ const_char **array
+ unsigned int arr_len = len(strings)
const_char *string
- int count = len(strings)
+ unsigned int str_len
+ unsigned int i
- lst = <const_char **>malloc(count * sizeof(const_char*))
- for i in range(count):
+ array = <const_char **>malloc(arr_len * sizeof(const_char*))
+ if not array:
+ raise MemoryError()
+
+ for i in range(arr_len):
string = _cfruni(strings[i])
- str_len = len(strings[i])
- lst[i] = <const_char *>malloc(str_len + 1)
- memcpy(lst[i], string, str_len + 1)
- # Note: Always make sure that the array is freed at the other end.
- return lst
+ str_len = len(string)
+ array[i] = <const_char *>malloc(str_len + 1)
+ memcpy(array[i], string, str_len + 1)
+ # Note: Always make sure that the array is freed at the other end
+ return array
-cdef convert_eina_list_strings_to_python_list(const_Eina_List *lst):
- cdef const_char *s
- ret = []
+cdef list convert_eina_list_strings_to_python_list(const_Eina_List *lst):
+ cdef:
+ const_char *s
+ list ret = []
while lst:
s = <const_char *>lst.data
if s != NULL:
@@ -122,7 +175,7 @@ cdef Eina_List *
convert_python_list_strings_to_eina_list(strings):
return lst
-cdef _object_list_to_python(const_Eina_List *lst):
+cdef list _object_list_to_python(const_Eina_List *lst):
ret = []
while lst:
ret.append(object_from_instance(<cEo *>lst.data))
diff --git a/include/efl.eo.pxd b/include/efl.eo.pxd
index 23338a5..e3a7c3b 100644
--- a/include/efl.eo.pxd
+++ b/include/efl.eo.pxd
@@ -20,10 +20,6 @@ from efl.c_eo cimport Eo_Class
from efl cimport Eina_List, const_Eina_List
from libc.string cimport const_char
-cdef extern from "string.h":
- void *memcpy(void *dst, void *src, int n)
- char *strdup(char *str)
-
cdef class Eo(object):
cdef cEo *obj
cdef readonly data
@@ -44,8 +40,8 @@ cdef char* _fruni(s)
cdef unicode _ctouni(const_char *s)
cdef const_char *_cfruni(s)
-cdef convert_array_of_strings_to_python_list(char **array, int array_length)
+cdef list convert_array_of_strings_to_python_list(char **array, int
array_length)
cdef const_char ** convert_python_list_strings_to_array_of_strings(list
strings)
-cdef convert_eina_list_strings_to_python_list(const_Eina_List *lst)
+cdef list convert_eina_list_strings_to_python_list(const_Eina_List *lst)
cdef Eina_List * convert_python_list_strings_to_eina_list(strings)
-cdef _object_list_to_python(const_Eina_List *lst)
+cdef list _object_list_to_python(const_Eina_List *lst)
--
------------------------------------------------------------------------------
Own the Future-Intel® Level Up Game Demo Contest 2013
Rise to greatness in Intel's independent game demo contest.
Compete for recognition, cash, and the chance to get your game
on Steam. $5K grand prize plus 10 genre and skill prizes.
Submit your demo by 6/6/13. http://p.sf.net/sfu/intel_levelupd2d