| Store | Cart

Use of internal ctypes objects

From: RICHARD MOSELEY <dick...@virgin.net>
Fri, 15 Jun 2012 09:28:47 +0100
I have a module which makes use of ctypes to interface to the IBM C-ISAM
library under linux. I have created a libpyisam.so library which combines
the two official libraries, libifisam.so and libifisamx.so and provides a
SONAME for the ctypes module (if that is still required).

My main object uses a dictionary in which the keys are the external
functions that can be called from the externl library, and the values are
initially tuples which define the arguments and return type for the
functions. The first time that a function is called, the __getattr__
function locates the function in the library then modifies the return type
and arguments according to the tuple stored in the value, this object is
then stored in place of the tuple so that subsequent calls simply use the
previous object.

To check whether the function has been previously converted, I make use of
internal objects within the ctypes module, namely, _SimpleCData and
_CFuncPtr. Is this a safe thing to do, bearing in mind that the objects are
documentated as internal?

In order to make the above paragraphs clear, I provide a cutdown version of
the object in question with a sample of the functions and the calling
convention used. Is there a better way to do this using ctypes:

from ctypes import *

class ISAMobject(dict):
  """
  The _func dictionary initially consists of:
    (args,...)                where the return type is c_int and arguments
are passed,
    (None,)                 where the return type is c_int but no arguments
are passed,
    (ret,(args,...))        where the return type is not c_int and
arguments are passed,
    (ret,None)             where the return type is not c_int and no
arguments are passed,
    None                     where there is no return type and no arguments
are passed
  """
  _func = {
    'isbegin'  : (None,),
    'iscluster' : (c_int, byref(keydesc)),
    'islangchk' : None,
    'islanginfo' : (c_char_p, (c_char_p,))
  }

  _const = {
    'iserrno' : c_int,
    'iscopyright' : c_char_p
  }

  _lib = cdll.LoadLibrary('./libpyisam.so')

  def __getattr__(self, name):
    func_info = self._func.get(name, 'NONE')
    if func_info == 'NONE':
       const_info = self._const.get(name, 'NONE')
       if const_info == 'NONE':
          raise AttributeError('Underlying ISAM library does not have %s
attribute' % name)
       if not isinstance(const_info, ctypes._SimpleCData):
          const_info = const_info.in_dll(self._lib, name)
          self._const[name] = const_info
       return const_info.value if hasattr(const_info, 'value') else
const_info
    elif not instance(func_info, ctypes._CFuncPtr):
       real_func = getattr(self._lib, name)
       if real_func is None:
          raise AttributeError('Underlying ISAM library does not support %s
function' % name)
       if func_info is None:
          real_func.restype = real.argtypes = None
       elif isinstance(func_info, list):
          real_func.restype, real_func.argtypes = func_info
       elif len(func_info) > 1 and isinstance(func_info[1], tuple):
          real_func.restype, real_func.argtypes = func_info
       elif isinstance(func_info, tuple):
          real_func.argtypes = func_info
       else:
          real_func.restype = func_info
       self._func[name] = func_info = real_func
    return func_info

Thank you in advance,
Richard Moseley

-- 
http://mail.python.org/mailman/listinfo/python-list

Recent Messages in this Thread
RICHARD MOSELEY Jun 15, 2012 08:28 am
Terry Reedy Jun 15, 2012 06:52 pm
Messages in this thread