From acac4f819ccafa6f6bb945626f2e21ec2b75074b Mon Sep 17 00:00:00 2001 From: Bryan Forbes Date: Thu, 1 Apr 2010 01:09:52 -0500 Subject: Cleaned up Makefile.am. Added the cython m4 files. Cleaned up afc.pxi. Make sure the event callback and installation proxy callback aquire the GIL. Implemented some cleanup before the error handlers raise. --- cython/Makefile.am | 10 ++++---- cython/afc.pxi | 3 --- cython/imobiledevice.pxd | 7 +----- cython/imobiledevice.pyx | 35 ++++++++++++++++++++------ cython/installation_proxy.pxi | 2 +- cython/property_list_client.pxi | 12 +++++++-- cython/sbservices.pxi | 30 ++++++++++++++++------ m4/ac_pkg_cython.m4 | 56 +++++++++++++++++++++++++++++++++++++++++ m4/cython_python.m4 | 7 ++++++ 9 files changed, 130 insertions(+), 32 deletions(-) create mode 100644 m4/ac_pkg_cython.m4 create mode 100644 m4/cython_python.m4 diff --git a/cython/Makefile.am b/cython/Makefile.am index 228ec0c..b1dea79 100644 --- a/cython/Makefile.am +++ b/cython/Makefile.am @@ -1,7 +1,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) -AM_LDFLAGS = $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) $(libplist_LIBS) $(libusbmuxd_LIBS) $(libgcrypt_LIBS) +AM_CFLAGS = $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(LFS_CFLAGS) +AM_LDFLAGS = $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) if HAVE_CYTHON @@ -30,9 +30,9 @@ EXTRA_DIST = imobiledevice.pyx imobiledevice.pxd $(PXIINCLUDES) imobiledevicedir = $(pyexecdir) imobiledevice_LTLIBRARIES = imobiledevice.la imobiledevice_la_SOURCES = imobiledevice.pyx -imobiledevice_la_CFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/src $(PYTHON_CPPFLAGS) $(libglib2_CFLAGS) $(libgthread2_CFLAGS) -imobiledevice_la_LDFLAGS = -module -avoid-version $(PYTHON_LDFLAGS) $(libglib2_LIBS) $(libgthread2_LIBS) -imobiledevice_la_LIBADD = $(top_builddir)/src/libimobiledevice.la +imobiledevice_la_CFLAGS = -I../include -I../src $(PYTHON_CPPFLAGS) $(AM_CFLAGS) +imobiledevice_la_LDFLAGS = -module -avoid-version -L$(libdir) $(PYTHON_LDFLAGS) $(AM_LDFLAGS) +imobiledevice_la_LIBADD = ../src/libimobiledevice.la imobiledevice.c: imobiledevice.pyx $(PXDINCLUDES) $(PXIINCLUDES) diff --git a/cython/afc.pxi b/cython/afc.pxi index ac9c927..1e2617a 100644 --- a/cython/afc.pxi +++ b/cython/afc.pxi @@ -66,9 +66,6 @@ cdef extern from "libimobiledevice/afc.h": afc_error_t afc_make_link(afc_client_t client, afc_link_type_t linktype, char *target, char *linkname) afc_error_t afc_set_file_time(afc_client_t client, char *path, uint64_t mtime) -cdef extern from *: - void free(void *ptr) - cdef class AfcError(BaseError): def __init__(self, *args, **kwargs): self._lookup_table = { diff --git a/cython/imobiledevice.pxd b/cython/imobiledevice.pxd index 8efd669..6bf75af 100644 --- a/cython/imobiledevice.pxd +++ b/cython/imobiledevice.pxd @@ -54,10 +54,5 @@ cdef extern from "libimobiledevice/lockdown.h": cdef class LockdownClient(Base): cdef lockdownd_client_t _c_client - cpdef int start_service(self, service) + cpdef int start_service(self, bytes service) cpdef goodbye(self) - -cpdef set_debug_level(int level) -cpdef event_subscribe(object callback) -cpdef event_unsubscribe() -cpdef get_device_list() diff --git a/cython/imobiledevice.pyx b/cython/imobiledevice.pyx index dc0fb88..b57db04 100644 --- a/cython/imobiledevice.pyx +++ b/cython/imobiledevice.pyx @@ -67,27 +67,40 @@ cdef class iDeviceError(BaseError): } BaseError.__init__(self, *args, **kwargs) -cpdef set_debug_level(int level): +def set_debug_level(int level): idevice_set_debug_level(level) cdef class iDeviceEvent: def __init__(self, *args, **kwargs): raise TypeError("iDeviceEvent cannot be instantiated") -cdef void idevice_event_cb(const_idevice_event_t c_event, void *user_data): + def __str__(self): + return 'iDeviceEvent: %s (%s)' % (self.event == IDEVICE_DEVICE_ADD and 'Add' or 'Remove', self.uuid) + + property event: + def __get__(self): + return self._c_event.event + property uuid: + def __get__(self): + return self._c_event.uuid + property conn_type: + def __get__(self): + return self._c_event.conn_type + +cdef void idevice_event_cb(const_idevice_event_t c_event, void *user_data) with gil: cdef iDeviceEvent event = iDeviceEvent.__new__(iDeviceEvent) event._c_event = c_event (user_data)(event) -cpdef event_subscribe(object callback): +def event_subscribe(object callback): cdef iDeviceError err = iDeviceError(idevice_event_subscribe(idevice_event_cb, callback)) if err: raise err -cpdef event_unsubscribe(): +def event_unsubscribe(): cdef iDeviceError err = iDeviceError(idevice_event_unsubscribe()) if err: raise err -cpdef get_device_list(): +def get_device_list(): cdef: char** devices int count @@ -214,10 +227,14 @@ cdef class LockdownError(BaseError): BaseError.__init__(self, *args, **kwargs) cdef class LockdownClient(Base): - def __cinit__(self, iDevice device not None, char *label=NULL, *args, **kwargs): + def __cinit__(self, iDevice device not None, bytes label="", *args, **kwargs): cdef: iDevice dev = device - lockdownd_error_t err = lockdownd_client_new_with_handshake(dev._c_dev, &(self._c_client), label) + lockdownd_error_t err + char* c_label = NULL + if label: + c_label = label + err = lockdownd_client_new_with_handshake(dev._c_dev, &(self._c_client), c_label) self.handle_error(err) def __dealloc__(self): @@ -229,7 +246,7 @@ cdef class LockdownClient(Base): cdef inline BaseError _error(self, int16_t ret): return LockdownError(ret) - cpdef int start_service(self, service): + cpdef int start_service(self, bytes service): cdef: uint16_t port lockdownd_error_t err @@ -242,6 +259,8 @@ cdef class LockdownClient(Base): cdef extern from *: ctypedef char* const_char_ptr "const char*" + void free(void *ptr) + void plist_free(plist.plist_t node) include "property_list_client.pxi" include "mobilesync.pxi" diff --git a/cython/installation_proxy.pxi b/cython/installation_proxy.pxi index 22e7e38..a8083d3 100644 --- a/cython/installation_proxy.pxi +++ b/cython/installation_proxy.pxi @@ -26,7 +26,7 @@ cdef extern from "libimobiledevice/installation_proxy.h": instproxy_error_t instproxy_restore(instproxy_client_t client, char *appid, plist.plist_t client_options, instproxy_status_cb_t status_cb, void *user_data) instproxy_error_t instproxy_remove_archive(instproxy_client_t client, char *appid, plist.plist_t client_options, instproxy_status_cb_t status_cb, void *user_data) -cdef void instproxy_notify_cb(const_char_ptr operation, plist.plist_t status, void *py_callback): +cdef void instproxy_notify_cb(const_char_ptr operation, plist.plist_t status, void *py_callback) with gil: (py_callback)(operation, plist.plist_t_to_node(status, False)) cdef class InstallationProxyError(BaseError): diff --git a/cython/property_list_client.pxi b/cython/property_list_client.pxi index 874f2b5..2f9ce76 100644 --- a/cython/property_list_client.pxi +++ b/cython/property_list_client.pxi @@ -4,8 +4,16 @@ cdef class PropertyListClient(Base): self.handle_error(self._send(n._c_node)) cpdef object receive(self): - cdef plist.plist_t c_node = NULL - self.handle_error(self._receive(&c_node)) + cdef: + plist.plist_t c_node = NULL + int16_t err + err = self._receive(&c_node) + try: + self.handle_error(err) + except BaseError, e: + if c_node != NULL: + plist_free(c_node) + raise return plist.plist_t_to_node(c_node) diff --git a/cython/sbservices.pxi b/cython/sbservices.pxi index f458bec..6eece0a 100644 --- a/cython/sbservices.pxi +++ b/cython/sbservices.pxi @@ -29,14 +29,16 @@ cdef class SpringboardServicesClient(Base): cdef sbservices_client_t _c_client def __cinit__(self, iDevice device not None, LockdownClient lockdown=None, *args, **kwargs): - cdef iDevice dev = device - cdef LockdownClient lckd + cdef: + iDevice dev = device + LockdownClient lckd if lockdown is None: lckd = LockdownClient(dev) else: lckd = lockdown - port = lockdown.start_service("com.apple.springboardservices") - self.handle_error(sbservices_client_new(dev._c_dev, port, &(self._c_client))) + port = lckd.start_service("com.apple.springboardservices") + err = SpringboardServicesError(sbservices_client_new(dev._c_dev, port, &(self._c_client))) + if err: raise err def __dealloc__(self): if self._c_client is not NULL: @@ -51,7 +53,14 @@ cdef class SpringboardServicesClient(Base): cdef: plist.plist_t c_node = NULL plist.Node node - self.handle_error(sbservices_get_icon_state(self._c_client, &c_node)) + sbservices_error_t err + err = sbservices_get_icon_state(self._c_client, &c_node) + try: + self.handle_error(err) + except BaseError, e: + if c_node != NULL: + plist_free(c_node) + raise node = plist.plist_t_to_node(c_node) return node def __set__(self, plist.Node newstate not None): @@ -63,6 +72,13 @@ cdef class SpringboardServicesClient(Base): bytes result char* pngdata = NULL uint64_t pngsize - self.handle_error(sbservices_get_icon_pngdata(self._c_client, bundleId, &pngdata, &pngsize)) - result = pngdata[:pngsize] + sbservices_error_t err + err = sbservices_get_icon_pngdata(self._c_client, bundleId, &pngdata, &pngsize) + try: + self.handle_error(err) + except BaseError, e: + raise + finally: + result = pngdata[:pngsize] + free(pngdata) return result diff --git a/m4/ac_pkg_cython.m4 b/m4/ac_pkg_cython.m4 new file mode 100644 index 0000000..aeae6a0 --- /dev/null +++ b/m4/ac_pkg_cython.m4 @@ -0,0 +1,56 @@ + +AC_DEFUN([AC_PROG_CYTHON],[ + AC_PATH_PROG([CYTHON],[cython]) + if test -z "$CYTHON" ; then + AC_MSG_WARN([cannot find 'cython' program. You should look at http://www.cython.org] or install your distribution specific cython package.) + CYTHON=false + elif test -n "$1" ; then + AC_MSG_CHECKING([for Cython version]) + [cython_version=`$CYTHON --version 2>&1 | grep 'Cython version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`] + AC_MSG_RESULT([$cython_version]) + if test -n "$cython_version" ; then + # Calculate the required version number components + [required=$1] + [required_major=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_major" ; then + [required_major=0] + fi + [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] + [required_minor=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_minor" ; then + [required_minor=0] + fi + [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] + [required_patch=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_patch" ; then + [required_patch=0] + fi + # Calculate the available version number components + [available=$cython_version] + [available_major=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_major" ; then + [available_major=0] + fi + [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] + [available_minor=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_minor" ; then + [available_minor=0] + fi + [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] + [available_patch=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_patch" ; then + [available_patch=0] + fi + if test $available_major -ne $required_major \ + -o $available_minor -ne $required_minor \ + -o $available_patch -lt $required_patch ; then + AC_MSG_WARN([Cython version >= $1 is required. You have $cython_version. You should look at http://www.cython.org]) + CYTHON=false + fi + else + AC_MSG_WARN([cannot determine Cython version]) + CYTHON=false + fi + fi + AC_SUBST([CYTHON_LIB]) +]) diff --git a/m4/cython_python.m4 b/m4/cython_python.m4 new file mode 100644 index 0000000..ba730d5 --- /dev/null +++ b/m4/cython_python.m4 @@ -0,0 +1,7 @@ +AC_DEFUN([CYTHON_PYTHON],[ + AC_REQUIRE([AC_PROG_CYTHON]) + AC_REQUIRE([AC_PYTHON_DEVEL]) + test "x$1" != "xno" || cython_shadow=" -noproxy" + AC_SUBST([CYTHON_PYTHON_OPT],[-python$cython_shadow]) + AC_SUBST([CYTHON_PYTHON_CPPFLAGS],[$PYTHON_CPPFLAGS]) +]) -- cgit v1.1-32-gdbae