Stephen Warren wrote:
> Attached is an updated version

Attached is another (final) updated version that removes a debug print I
was using. Sigh.

? concordance/.deps
? concordance/.libs
? concordance/Makefile
? concordance/Makefile.in
? concordance/aclocal.m4
? concordance/autom4te.cache
? concordance/concordance
? concordance/config.guess
? concordance/config.h
? concordance/config.h.in
? concordance/config.log
? concordance/config.status
? concordance/config.sub
? concordance/configure
? concordance/depcomp
? concordance/install-sh
? concordance/libtool
? concordance/ltmain.sh
? concordance/missing
? concordance/stamp-h1
? libconcord/.deps
? libconcord/.libconcord.cpp.swp
? libconcord/.libs
? libconcord/.remote.h.swp
? libconcord/Makefile
? libconcord/Makefile.in
? libconcord/aclocal.m4
? libconcord/autom4te.cache
? libconcord/binaryfile.lo
? libconcord/config.guess
? libconcord/config.h
? libconcord/config.h.in
? libconcord/config.log
? libconcord/config.status
? libconcord/config.sub
? libconcord/configure
? libconcord/depcomp
? libconcord/install-sh
? libconcord/libconcord.la
? libconcord/libconcord.lo
? libconcord/libtool
? libconcord/libusbhid.lo
? libconcord/ltmain.sh
? libconcord/missing
? libconcord/remote.lo
? libconcord/remote_z.lo
? libconcord/stamp-h1
? libconcord/usblan.lo
? libconcord/web.lo
? libconcord/bindings/python/.README.swp
? libconcord/bindings/python/.libconcord.py.swp
? libconcord/bindings/python/build
? libconcord/bindings/python/libconcord.pyc
Index: libconcord/bindings/python/README
===================================================================
RCS file: /cvsroot/concordance/concordance/libconcord/bindings/python/README,v
retrieving revision 1.1
diff -u -p -r1.1 README
--- libconcord/bindings/python/README	15 Apr 2008 02:34:08 -0000	1.1
+++ libconcord/bindings/python/README	28 Jun 2008 05:55:29 -0000
@@ -32,3 +32,14 @@ the bindings to your PYTHONPATH. For exa
 
 export PYTHONPATH=/path/to/libconcord/bindings/python
 
+Debugging
+====================
+
+If you set the environment variable LIBCONCORD_PY_TRACE to string "1", then
+libconcord.py will trace all function calls. This may prove helpful when
+debugging client applications.
+
+For example, in bash:
+
+LIBCONCORD_PY_TRACE=1 ./congruity /path/to/Connectivity.EZHex
+
Index: libconcord/bindings/python/libconcord.py
===================================================================
RCS file: /cvsroot/concordance/concordance/libconcord/bindings/python/libconcord.py,v
retrieving revision 1.1
diff -u -p -r1.1 libconcord.py
--- libconcord/bindings/python/libconcord.py	8 Apr 2008 09:50:29 -0000	1.1
+++ libconcord/bindings/python/libconcord.py	28 Jun 2008 05:55:29 -0000
@@ -1,5 +1,5 @@
 #
-# vi: formatoptions+=tc textwidth=80 tabstop=8 shiftwidth=8 noexpandtab:
+# vi: formatoptions+=tc textwidth=80 tabstop=8 shiftwidth=4 expandtab:
 #
 # $Id: libconcord.py,v 1.1 2008/04/08 09:50:29 jaymzh Exp $
 #
@@ -18,19 +18,37 @@
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 #
 
-
 from ctypes import *
 import platform
+import os
 import sys
+import traceback
+
+# Debug request parsing
+
+debug = (os.environ.get("LIBCONCORD_PY_TRACE", "0") == "1")
+
+# Define the libconcord ABI this libconcord.py corresponds to
+# Bump this when the .so file version gets bumped
+
+ABI_VERSION = 0
+
+# Load the DLL
 
-# Internal DLL handle
 if platform.system() == 'Windows':
     _dll = cdll.LoadLibrary('libconcord.dll')
 else:
-    _dll = cdll.LoadLibrary('libconcord.so.0')
+    _dll = cdll.LoadLibrary('libconcord.so.' + str(ABI_VERSION))
+
+# Public libconcord API: Custom types
+
+# typedef void (*lc_callback)(uint32_t, uint32_t, uint32_t, void*);
+callback_type = CFUNCTYPE(None, c_uint, c_uint, c_uint, py_object)
+
+# Exception types
 
-# This exception may be raised by any function that returns an LC_ERROR_*.
 class LibConcordException(Exception):
+    """This exception may be raised by any function that returns an LC_ERROR_*."""
     def __init__(self, func, result):
         self.func = func
         self.result = result
@@ -46,7 +64,48 @@ class LibConcordException(Exception):
             repr(self.result_str)
         )
 
+# Helpers for parameter prototyping
+
+class _param(object):
+    def __init__(self, name, ctypes_type):
+        self.name = name
+        self.ctypes_type = ctypes_type
+
+class _in(_param):
+    def real_ctypes_type(self):
+        return self.ctypes_type
+
+class _out(_param):
+    def real_ctypes_type(self):
+        return POINTER(self.ctypes_type)
+
+# Helpers for parameter tracing
+
+def _dump_simple(type):
+    def _dump_simple_imp(value):
+        if not isinstance(value, type):
+            value = type(value)
+        return repr(value.value)
+    return _dump_simple_imp
+
+def _dump_pointer(name):
+    def _dump_pointer_imp(value):
+        return "<<%s @0x%08x>>" % (name, addressof(value))
+    return _dump_pointer_imp
+
+_dumpers = {
+    c_char_p:         _dump_simple(c_char_p),
+    c_int:            _dump_simple(c_int),
+    c_long:           _dump_simple(c_long),
+    c_uint:           _dump_simple(c_uint),
+    c_ulong:          _dump_simple(c_ulong),
+    POINTER(c_ubyte): _dump_pointer('buffer'),
+    callback_type:    _dump_pointer('function'),
+    py_object:        _dump_simple(py_object),
+}
+
 # Internal function result checking functionality
+
 class _CheckRetCode(object):
     def __init__(self, func_name):
         self.func_name = func_name
@@ -55,21 +114,88 @@ class _CheckRetCode(object):
         result = args[0]
         if result != 0:
             raise LibConcordException(self.func_name, result)
-        
+
+# Internal function tracing functionality
+
+_byref_type = type(byref(c_int()))
+def from_param(obj):
+    if type(obj) == _byref_type:
+        return obj._obj
+    if isinstance(obj, _Pointer):
+        return obj.contents
+    raise TypeError, "Output parameters should be byref/pointers"
+
+class _DebugWrapper(object):
+    def __init__(self, callable):
+        self.callable = callable
+
+    def __call__(self, *args):
+        sys.stdout.write("libconcord." + self.callable.__name__ + "(")
+        delim = ""
+        for (val, proto) in zip(args, self.callable._lcpy_protos):
+            if isinstance(proto, _param):
+                name = proto.name
+                if isinstance(proto, _in):
+                    try:
+                        type = proto.ctypes_type
+                        value = _dumpers[type](val)
+                    except:
+                        value = "???"
+                else:
+                    value = "<<out>>"
+            else:
+                name = "???"
+                value = "???"
+            sys.stdout.write("%s%s=%s" % (delim, name, value))
+            delim = ", "
+        print ")"
+        try:
+            ret = self.callable(*args)
+            print "    Returned: " + repr(ret)
+            for (val, proto) in zip(args, self.callable._lcpy_protos):
+                if not isinstance(proto, _out):
+                    continue
+                name = proto.name
+                type = proto.ctypes_type
+                try:
+                    value = _dumpers[type](from_param(val))
+                except:
+                    value = "???"
+                print "    <<out>> %s=%s" % (name, value)
+            return ret
+        except:
+            print "    Threw: "
+            s = traceback.format_exc()
+            for sl in s.split('\n'):
+                print "        " + sl
+            raise
+
 # Internal ctypes function wrapper creation
+
 def _create_func(
     func_name,
     error_checker,
-    *args
+    rettype,
+    *protos
 ):
-    ftype = CFUNCTYPE(*args)
+    def real_ctypes_type(type):
+        if not isinstance(type, _param):
+            return type
+        return type.real_ctypes_type()
+    real_protos = [real_ctypes_type(x) for x in protos]
+    ftype = CFUNCTYPE(rettype, *real_protos)
     f = ftype((func_name, _dll))
+    f._lcpy_rettype = rettype
+    f._lcpy_protos = protos
+    f.__name__ = func_name
     if error_checker:
         f.errcheck = error_checker(func_name)
+    if debug:
+        f = _DebugWrapper(f)
+    f.__name__ = func_name
     return f
 
-# typedef void (*lc_callback)(uint32_t, uint32_t, uint32_t, void*);
-callback_type = CFUNCTYPE(None, c_uint, c_uint, c_uint, py_object)
+# Public libconcord API: Function prototypes
 
 # const char *get_mfg();
 get_mfg = _create_func(
@@ -241,7 +367,7 @@ get_serial = _create_func(
     'get_serial',
     None,
     c_char_p,
-    c_int
+    _in('p', c_int)
 )
 
 # int get_config_bytes_used();
@@ -326,7 +452,7 @@ delete_block = _create_func(
     'delete_blob',
     _CheckRetCode,
     c_int,
-    POINTER(c_ubyte)
+    _in('ptr', POINTER(c_ubyte))
 );
 
 LC_FILE_TYPE_CONNECTIVITY  = 0
@@ -339,9 +465,9 @@ identify_file = _create_func(
     'identify_file',
     _CheckRetCode,
     c_int,
-    POINTER(c_ubyte),
-    c_uint,
-    POINTER(c_int)
+    _in('in', POINTER(c_ubyte)),
+    _in('size', c_uint),
+    _out('type', c_int)
 )
 
 # int init_concord();
@@ -363,8 +489,8 @@ get_identity = _create_func(
     'get_identity',
     _CheckRetCode,
     c_int,
-    callback_type,
-    py_object
+    _in('cb', callback_type),
+    _in('cb_arg', py_object)
 )
 
 # int reset_remote();
@@ -393,8 +519,8 @@ post_connect_test_success = _create_func
     'post_connect_test_success',
     _CheckRetCode,
     c_int,
-    POINTER(c_ubyte),
-    c_uint
+    _in('data', POINTER(c_ubyte)),
+    _in('size', c_uint)
 )
 
 # int post_preconfig(uint8_t *data, uint32_t size);
@@ -402,8 +528,8 @@ post_preconfig = _create_func(
     'post_preconfig',
     _CheckRetCode,
     c_int,
-    POINTER(c_ubyte),
-    c_uint
+    _in('data', POINTER(c_ubyte)),
+    _in('size', c_uint)
 )
 
 # int post_postconfig(uint8_t *data, uint32_t size);
@@ -411,8 +537,8 @@ post_postconfig = _create_func(
     'post_postconfig',
     _CheckRetCode,
     c_int,
-    POINTER(c_ubyte),
-    c_uint
+    _in('data', POINTER(c_ubyte)),
+    _in('size', c_uint)
 )
 
 # int post_postfirmware(uint8_t *data, uint32_t size);
@@ -420,8 +546,8 @@ post_postfirmware = _create_func(
     'post_postfirmware',
     _CheckRetCode,
     c_int,
-    POINTER(c_ubyte),
-    c_uint
+    _in('data', POINTER(c_ubyte)),
+    _in('size', c_uint)
 )
 
 # int invalidate_flash();
@@ -437,10 +563,10 @@ read_config_from_remote = _create_func(
     'read_config_from_remote',
     _CheckRetCode,
     c_int,
-    POINTER(POINTER(c_ubyte)),
-    POINTER(c_uint),
-    callback_type,
-    py_object
+    _out('out', POINTER(c_ubyte)),
+    _out('size', c_uint),
+    _in('cb', callback_type),
+    _in('cb_arg', py_object)
 )
 
 # int write_config_to_remote(uint8_t *in, uint32_t size,
@@ -449,10 +575,10 @@ write_config_to_remote = _create_func(
     'write_config_to_remote',
     _CheckRetCode,
     c_int,
-    POINTER(c_ubyte),
-    c_uint,
-    callback_type,
-    py_object
+    _in('in', POINTER(c_ubyte)),
+    _in('size', c_uint),
+    _in('cb', callback_type),
+    _in('cb_arg', py_object)
 )
 
 # int read_file(char *file_name, uint8_t **out, uint32_t *size);
@@ -460,9 +586,9 @@ read_file = _create_func(
     'read_file',
     _CheckRetCode,
     c_int,
-    c_char_p,
-    POINTER(POINTER(c_ubyte)),
-    POINTER(c_uint)
+    _in('file_name', c_char_p),
+    _out('out', POINTER(c_ubyte)),
+    _out('size', c_uint)
 )
 
 # int write_config_to_file(uint8_t *in, uint32_t size, char *file_name,
@@ -471,10 +597,10 @@ write_config_to_file = _create_func(
     'write_config_to_file',
     _CheckRetCode,
     c_int,
-    POINTER(c_ubyte),
-    c_uint,
-    c_char_p,
-    c_int
+    _in('in', POINTER(c_ubyte)),
+    _in('size', c_uint),
+    _in('file_name', c_char_p),
+    _in('binary', c_int)
 )
 
 # int verify_remote_config(uint8_t *in, uint32_t size, lc_callback cb,
@@ -483,10 +609,10 @@ verify_remote_config = _create_func(
     'verify_remote_config',
     _CheckRetCode,
     c_int,
-    POINTER(c_ubyte),
-    c_uint,
-    callback_type,
-    py_object
+    _in('in', POINTER(c_ubyte)),
+    _in('size', c_uint),
+    _in('cb', callback_type),
+    _in('cb_arg', py_object)
 )
 
 # int erase_config(uint32_t size, lc_callback cb, void *cb_arg);
@@ -494,9 +620,9 @@ erase_config = _create_func(
     'erase_config',
     _CheckRetCode,
     c_int,
-    c_uint,
-    callback_type,
-    py_object
+    _in('size', c_uint),
+    _in('cb', callback_type),
+    _in('cb_arg', py_object)
 )
 
 # int find_config_binary(uint8_t *config, uint32_t config_size,
@@ -505,10 +631,10 @@ find_config_binary = _create_func(
     'find_config_binary',
     _CheckRetCode,
     c_int,
-    POINTER(c_ubyte),
-    c_uint,
-    POINTER(POINTER(c_ubyte)),
-    POINTER(c_uint)
+    _in('config', POINTER(c_ubyte)),
+    _in('config_size', c_uint),
+    _out('binary_ptr', POINTER(c_ubyte)),
+    _out('binary_size', c_uint)
 )
 
 # int erase_safemode(lc_callback cb, void *cb_arg);
@@ -516,8 +642,8 @@ erase_safemode = _create_func(
     'erase_safemode',
     _CheckRetCode,
     c_int,
-    callback_type,
-    py_object
+    _in('cb', callback_type),
+    _in('cb_arg', py_object)
 )
 
 # int read_safemode_from_remote(uint8_t **out, uint32_t *size, lc_callback cb,
@@ -526,20 +652,20 @@ read_safemode_from_remote = _create_func
     'read_safemode_from_remote',
     _CheckRetCode,
     c_int,
-    POINTER(POINTER(c_ubyte)),
-    POINTER(c_ubyte),
-    callback_type,
-    py_object
+    _out('out', POINTER(c_ubyte)),
+    _out('size', c_ubyte),
+    _in('cb', callback_type),
+    _in('cb_arg', py_object)
 )
 
-# int write_safemode_to_file(uint8_t *in, uint32_t size,char *file_name);
+# int write_safemode_to_file(uint8_t *in, uint32_t size, char *file_name);
 write_safemode_to_file = _create_func(
     'write_safemode_to_file',
     _CheckRetCode,
     c_int,
-    POINTER(c_ubyte),
-    c_uint,
-    c_char_p
+    _in('in', POINTER(c_ubyte)),
+    _in('size', c_uint),
+    _in('file_name', c_char_p)
 )
 
 # int is_fw_update_supported(int direct);
@@ -547,7 +673,7 @@ is_fw_update_supported = _create_func(
     'is_fw_update_supported',
     None,
     c_int,
-    c_int
+    _in('direct', c_int)
 )
 
 # int is_config_safe_after_fw();
@@ -576,9 +702,9 @@ erase_firmware = _create_func(
     'erase_firmware',
     _CheckRetCode,
     c_int,
-    c_int,
-    callback_type,
-    py_object
+    _in('direct', c_int),
+    _in('cb', callback_type),
+    _in('cb_arg', py_object)
 )
 
 # int read_firmware_from_remote(uint8_t **out, uint32_t *size, lc_callback cb,
@@ -587,10 +713,10 @@ read_firmware_from_remote = _create_func
     'read_firmware_from_remote',
     _CheckRetCode,
     c_int,
-    POINTER(POINTER(c_ubyte)),
-    POINTER(c_uint),
-    callback_type,
-    py_object
+    _out('out', POINTER(c_ubyte)),
+    _out('size', c_uint),
+    _in('cb', callback_type),
+    _in('cb_arg', py_object)
 )
 
 # int write_firmware_to_remote(uint8_t *in, uint32_t size, int direct,
@@ -599,11 +725,11 @@ write_firmware_to_remote = _create_func(
     'write_firmware_to_remote',
     _CheckRetCode,
     c_int,
-    POINTER(c_ubyte),
-    c_uint,
-    c_int,
-    callback_type,
-    py_object
+    _in('in', POINTER(c_ubyte)),
+    _in('size', c_uint),
+    _in('direct', c_int),
+    _in('cb', callback_type),
+    _in('cb_arg', py_object)
 )
 
 # int write_firmware_to_file(uint8_t *in, uint32_t size, char *file_name,
@@ -612,10 +738,10 @@ write_firmware_to_file = _create_func(
     'write_firmware_to_file',
     _CheckRetCode,
     c_int,
-    POINTER(c_ubyte),
-    c_uint,
-    c_char_p,
-    c_int
+    _in('in', POINTER(c_ubyte)),
+    _in('size', c_uint),
+    _in('file_name', c_char_p),
+    _in('binary', c_int)
 )
 
 # int extract_firmware_binary(uint8_t *xml, uint32_t xml_size, uint8_t **out,
@@ -624,10 +750,10 @@ extract_firmware_binary = _create_func(
     'extract_firmware_binary',
     _CheckRetCode,
     c_int,
-    POINTER(c_ubyte),
-    c_uint,
-    POINTER(POINTER(c_ubyte)),
-    POINTER(c_uint)
+    _in('xml', POINTER(c_ubyte)),
+    _in('xml_size', c_uint),
+    _out('out', POINTER(c_ubyte)),
+    _out('size', c_uint)
 )
 
 # int learn_ir_commands(uint8_t *data, uint32_t size, int post);
@@ -635,8 +761,8 @@ learn_ir_commands = _create_func(
     'learn_ir_commands',
     _CheckRetCode,
     c_int,
-    POINTER(c_ubyte),
-    c_uint,
-    c_int
+    _in('data', POINTER(c_ubyte)),
+    _in('size', c_uint),
+    _in('post', c_int)
 )
 
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
concordance-devel mailing list
concordance-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/concordance-devel

Reply via email to