ctypes-commit Mailing List for ctypes (Page 10)
Brought to you by:
theller
You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
(8) |
May
(90) |
Jun
(143) |
Jul
(106) |
Aug
(94) |
Sep
(84) |
Oct
(163) |
Nov
(60) |
Dec
(58) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(128) |
Feb
(79) |
Mar
(227) |
Apr
(192) |
May
(179) |
Jun
(41) |
Jul
(53) |
Aug
(103) |
Sep
(28) |
Oct
(38) |
Nov
(81) |
Dec
(17) |
2006 |
Jan
(184) |
Feb
(111) |
Mar
(188) |
Apr
(67) |
May
(58) |
Jun
(123) |
Jul
(73) |
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
From: Thomas H. <th...@us...> - 2006-05-26 12:52:00
|
Update of /cvsroot/ctypes/ctypes/docs/manual In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv6383 Modified Files: reference.txt Log Message: Index: reference.txt =================================================================== RCS file: /cvsroot/ctypes/ctypes/docs/manual/reference.txt,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** reference.txt 26 May 2006 10:29:03 -0000 1.3 --- reference.txt 26 May 2006 12:51:50 -0000 1.4 *************** *** 2,76 **** ================ ! ``ARRAY`` ``ArgumentError`` ! ``Array`` ``BigEndianStructure`` ! ``CDLL`` ! ``CFUNCTYPE`` ! ``DllCanUnloadNow`` ! ``DllGetClassObject`` ! ``FormatError`` ! ``GetLastError`` ! ``HRESULT`` ! ``LibraryLoader`` ! ``LittleEndianStructure`` ! ``OleDLL`` ! ``POINTER`` ! ``PYFUNCTYPE`` ! ``PyDLL`` ! ``RTLD_GLOBAL`` ! ``RTLD_LOCAL`` ! ``SetPointerType`` ! ``Structure`` ! ``Union`` ! ``WINFUNCTYPE`` ! ``WinDLL`` ! ``WinError`` ! ``addressof`` ! ``alignment`` ! ``byref`` ! ``c_buffer`` ! ``c_byte`` ! ``c_char`` ``c_char_p`` ``c_double`` ``c_float`` ``c_int`` ! ``c_int16`` ! ``c_int32`` ! ``c_int64`` ! ``c_int8`` ``c_long`` ``c_longlong`` ! ``c_short`` ``c_size_t`` ``c_ubyte`` ! ``c_uint`` ``c_uint16`` ``c_uint32`` ``c_uint64`` ``c_uint8`` ``c_ulong`` ``c_ulonglong`` ``c_ushort`` ``c_void_p`` ``c_voidp`` ! ``c_wchar`` ``c_wchar_p`` ! ``cast`` ``cdll`` ! ``create_string_buffer`` ``create_unicode_buffer`` ! ``memmove`` ! ``memset`` ``oledll`` ! ``pointer`` ``py_object`` ``pydll`` ``pythonapi`` ``resize`` ``set_conversion_mode`` ``sizeof`` ``string_at`` ``windll`` ``wstring_at`` --- 2,195 ---- ================ ! ``addressof(obj)`` ! Returns the address of ``obj`` as integer. ``obj`` must be an ! instance of a ctypes type. ! ! ``alignment(obj)`` ! Returns the byte alignment requirement of ``obj``. ! ``ArgumentError`` ! This exception is raised when a parameter cannot be used in a ! foreign function call. ! ! .. undocumented because deprecated. ! ``ARRAY`` ! ``Array`` ! ``BigEndianStructure`` ! Base class. ! ! ``byref(obj)`` : funcdesc ! Returns a light-weight pointer to a ctypes instance. The returned ! object can only be used as function call parameter. Behaves the ! same as calling ``pointer(object)``, but is a lot faster. Same as ! ``&object`` in C. ! ! ! .. undocumented because deprecated. ! ``c_buffer`` ! ! .. topic:: ``c_byte`` ! :class: funcdef ! ! Represents the C ``char`` data type, interpreted as integer. ! ``c_char_p`` + + ``c_char`` + ``c_double`` + ``c_float`` + + + ``c_int8``, ``c_int16``, ``c_int32``, ``c_int64`` + + ``c_short`` + ``c_int`` ! ``c_long`` + ``c_longlong`` ! ``c_size_t`` + ``c_ubyte`` ! ``c_uint16`` + ``c_uint32`` + ``c_uint64`` + ``c_uint8`` + + ``c_uint`` + ``c_ulong`` + ``c_ulonglong`` + ``c_ushort`` + ``c_void_p`` + ``c_voidp`` ! ``c_wchar_p`` ! ! ``c_wchar`` ! ! ``cast(obj, type)`` ! This function is similar to the cast operator in C. Returns a new ! instance of ``type`` which shares the memory block of ``object``. ! ``type`` must be a pointer type. ! ! ! ``CDLL`` ! ``cdll`` ! ! ``CFUNCTYPE`` ! ! ``create_string_buffer(init_or_size[, size])`` ! Convenience function which creates a mutable character buffer. ! ! ``init`` must be a string. If ``size`` is supplied it must be a ! positive integer that specifies the size of the buffer, otherwise ! the length of the ``init`` string is used. ! This function returns a ctypes array of characters ``c_char``. ! ``create_unicode_buffer`` ! Convenience function which creates a mutable character buffer. ! ! ``init`` must be a unicode string. If ``size`` is supplied it ! must be a positive integer that specifies the size of the buffer, ! otherwise the length of the ``init`` string is used. This ! function returns a ctypes array of wide characters ``c_wchar``. ! ! ``DllCanUnloadNow`` ! Windows only. This function is used to implement COM servers. ! ! ``DllGetClassObject`` ! Windows only. This function is used to implement COM servers. ! ! ``FormatError([code], [descr])`` ! Windows only. Returns a textual description of the error code, or ! the last error code set by Windows. ! ! ``GetLastError()`` ! Windows only. Return the last error code set by Windows in the ! calling thread. ! ! ``HRESULT`` ! ! ``LibraryLoader`` ! Instances of this type are used to load shared libraries. ! ! ``LittleEndianStructure`` ! ! ``memmove(dst, src, count)`` ! Same as the standard C ``memmove`` library function: copies ! ``count`` bytes from ``src`` to ``dst``. ``dst`` and ``src`` must ! be integers or anything else that can be converted into a pointer. ! ! ``memset(dst, c, count)`` ! Same as the standard C ``memset`` function. Fills the memory block ! at address ``dst`` with ``count`` bytes of value ``c``. ``dst`` must be ! an integer specifying an address, or a ctypes instance. ! ! ``OleDLL`` ! ``oledll`` ! ! ``POINTER(type)`` ! This factory function creates and returns a new ctypes type. ! Pointer types are cached, so calling this function repeatedly is ! cheap. ! ! ``pointer(obj)`` ! This function creates a new pointer instance, pointing to ``obj`` ! which must be an instance of a ctypes type. The return pointer is ! of type ``POINTER(type(obj))``. If you just want to pass a ! pointer to this object to a foreign function call, you should use ! ``byref(obj)`` instead which is much faster. ! ``py_object`` + + ``PyDLL`` + ``pydll`` + + ``PYFUNCTYPE`` + ``pythonapi`` + ``resize`` + + ``RTLD_GLOBAL`` + + ``RTLD_LOCAL`` + ``set_conversion_mode`` + + ``SetPointerType`` + ``sizeof`` + ``string_at`` + + ``Structure`` + + ``Union`` + + ``WinDLL`` + ``windll`` + + ``WinError`` + + ``WINFUNCTYPE`` + ``wstring_at`` |
From: Thomas H. <th...@us...> - 2006-05-26 12:50:57
|
Update of /cvsroot/ctypes/ctypes/docs/manual In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv5990 Added Files: ctypes.tex Log Message: --- NEW FILE: ctypes.tex --- ``ctypes`` is a foreign function library for Python. .. include:: tutorial.txt .. include:: reference.txt |
From: Thomas H. <th...@us...> - 2006-05-26 12:50:12
|
Update of /cvsroot/ctypes/ctypes/docs/manual In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv5894 Added Files: mkpydoc1.py Log Message: New version from grubert. --- NEW FILE: mkpydoc1.py --- #!/usr/bin/python # Convert the reStructuredText docs to LaTeX for use in Python docs # This script is a hacked version taken from the Optik SVN repository. import sys, os import re import rfc822 from distutils.dep_util import newer_group, newer from docutils.core import Publisher from docutils.readers.standalone import Reader as StandaloneReader from docutils.transforms import Transform from docutils.writers.latex2e import Writer as LaTeXWriter, LaTeXTranslator from docutils import nodes class OptikReader(StandaloneReader): #default_transforms = (StandaloneReader.default_transforms + # (ReplacementTransform,)) pass # python 2.3 if not hasattr(__builtins__,"set"): import sets set = sets.Set if not hasattr(__builtins__,"sorted"): def sorted(list): if hasattr(list,"sort"): return list.sort() # maybe it is sorted return list from markup import codemarkup missing = set() class PyLaTeXWriter(LaTeXWriter): def __init__(self): LaTeXWriter.__init__(self) self.translator_class = PyLaTeXTranslator class PyLaTeXTranslator(LaTeXTranslator): remap_title = { } roman = (None,None,"ii","iii","iv","v") refuri_override = { "reference" : "reference-guide", "callbacks" : "option-callbacks", } def __init__(self, document): LaTeXTranslator.__init__(self, document) self.label_prefix = "" self.docinfo = {} self.head_prefix = [] self.head = [] self.body_prefix = [] self.in_title = False self.in_anydesc = False # _title is different if it is a funcdesc # Disable a bunch of methods from the base class. empty_method = lambda self: None for nodetype in ('field_argument', 'field_body', 'field_list', 'field_name'): setattr(self, 'visit_' + nodetype, empty_method) setattr(self, 'depart_' + nodetype, empty_method) self.head_prefix = [] # definitions must be guarded if multiple modules are included self.definitions = [ "\\ifx\\locallinewidth\\undefined\\newlength{\\locallinewidth}\\fi\n" "\\setlength{\\locallinewidth}{\\linewidth}\n" ] def astext(self): return ''.join(self.definitions + self.head_prefix + self.head + self.body_prefix + self.body + self.body_suffix) def set_label_prefix(self, text): self.label_prefix = text.replace(" ","-") def generate_section_label(self, title): title = title.lower() title = re.sub(r'\([^\)]*\)', '', title) title = re.sub(r'[^\w\s\-]', '', title) title = re.sub(r'\b(the|an?|and|your|are)\b', '', title) title = re.sub(r'(example \d+).*', r'\1', title) return self.label_prefix + "-" + "-".join(title.split()) def visit_document(self, node): pass def depart_document(self, node): pass def visit_docinfo(self, node): pass def depart_docinfo(self, node): # module and summary are mandatory self.body.append( "\\section{\\module{%(module)s} --- %(summary)s}\n" % self.docinfo ) if self.docinfo.has_key("moduletype"): self.body.append( "\\declaremodule{%(moduletype)s}{%(module)s}\n" % self.docinfo ) if self.docinfo.has_key("moduleauthor"): self.body.append( "\\moduleauthor{%(moduleauthor)s}{%(moduleauthoremail)s}\n" % self.docinfo ) if self.docinfo.has_key("synopsis"): self.body.append( "\\modulesynopsis{%(synopsis)s}\n" % self.docinfo ) if self.docinfo.has_key("release"): self.body.append( "\\release{%(release)s}\n" % self.docinfo ) if self.docinfo.has_key("shortversion"): self.body.append( "\\setshortversion{%(shortversion)s}\n" % self.docinfo ) if self.docinfo.has_key("sectionauthor"): self.body.append( "\\sectionauthor{%(sectionauthor)s}{%(sectionauthoremail)s}\n" % self.docinfo ) if self.docinfo.has_key("versionadded"): self.body.append( "\\versionadded{%(versionadded)s}\n" % self.docinfo ) def visit_docinfo_item(self, node, name): if name == "author": (ename, email) = rfc822.parseaddr(node.astext()) self.docinfo["moduleauthor"] = ename self.docinfo["moduleauthoremail"] = email raise nodes.SkipNode def depart_docinfo_item(self, node): pass def visit_field(self, node): if isinstance(node.parent, nodes.docinfo): name = node[0].astext().lower().replace(" ","") if name == "moduleauthor": (ename, email) = rfc822.parseaddr(node[1].astext()) self.docinfo["moduleauthor"] = ename self.docinfo["moduleauthoremail"] = email elif name in ("author", "sectionauthor") : (ename, email) = rfc822.parseaddr(node[1].astext()) self.docinfo["sectionauthor"] = ename self.docinfo["sectionauthoremail"] = email else: if name == "module": self.set_label_prefix(node[1].astext()) self.docinfo[name] = node[1].astext() raise nodes.SkipNode _quoted_string_re = re.compile(r'\"[^\"]*\"') _short_opt_string_re = re.compile(r'-[a-zA-Z]') _long_opt_string_re = re.compile(r'--[a-zA-Z-]+') _identifier_re = re.compile(r'[a-zA-Z_][a-zA-Z_0-9]*' r'(\.[a-zA-Z_][a-zA-Z_0-9]*)*' r'(\(\))?$') def visit_literal(self, node): assert isinstance(node[0], nodes.Text) text = node[0].data if self.in_title: cmd = None elif self._quoted_string_re.match(text): cmd = 'code' elif self._short_opt_string_re.match(text): cmd = 'programopt' elif self._long_opt_string_re.match(text): cmd = 'longprogramopt' text = text[2:] elif self._identifier_re.match(text): cmd = codemarkup.get(text) if cmd is None: ## print "warning: unrecognized code word %r" % text missing.add(text) cmd = 'code' else: cmd = 'code' self.literal = 1 node[0].data = text if cmd is not None: self.body.append('\\%s{' % cmd) # use topics for special environments def visit_topic(self, node): classes = node.get('classes', ['topic', ]) if classes[0] in ('datadesc', 'datadescni', 'excdesc', 'classdesc*', 'csimplemacrodesc', 'ctypedesc', 'memberdesc', 'memberdescni', 'cvardesc', 'excclassdesc', 'funcdesc', 'funcdescni', 'methoddesc', 'methoddescni', 'cmemberdesc', 'classdesc', 'cfuncdesc'): self.body.append('\n\\begin{%s}' % classes[0]) self.context.append('\\end{%s}\n' % classes[0]) self.in_anydesc = classes[0] else: self.context.append('') def depart_topic(self, node): self.in_anydesc = False self.body.append(self.context.pop()) # use definition lists for special environments # # definition_list # defintion_list_item # term # classifier # definition # paragraph ? def visit_definition_list(self, node): pass def depart_definition_list(self, node): pass def visit_definition_list_item(self, node): self._dl_item = [] def depart_definition_list_item(self, node): try: self.body.append(self.context.pop()) except: self.body.append("% WARN definition list without classifier\n") def visit_term(self, node): self._dl_item.append(node.astext()) raise nodes.SkipNode def depart_term(self, node): pass def visit_classifier(self, node): # TODO here it should be decided if it is latex or python classifier = node.astext() if classifier in ('datadesc', 'datadescni', 'excdesc', 'classdesc*', 'csimplemacrodesc', 'ctypedesc', 'memberdesc', 'memberdescni', 'cvardesc', 'excclassdesc', 'funcdesc', 'funcdescni', 'methoddesc', 'methoddescni', 'cmemberdesc', 'classdesc', 'cfuncdesc'): pass else: classifier = 'datadescni' self.body.append('\n\\begin{%s}' % classifier) self.in_anydesc = classifier self.body.append(self.anydesc_title(self._dl_item.pop())) self.context.append('\\end{%s}\n' % classifier) self.in_anydesc = None raise nodes.SkipNode def depart_classifier(self, node): pass def visit_definition(self, node): pass def depart_definition(self, node): self.body.append('\n') def depart_literal(self, node): if not self.in_title: self.body.append('}') self.literal = 0 def visit_literal_block(self, node): self.body.append("\\begin{verbatim}\n") self.verbatim = 1 def depart_literal_block(self, node): self.verbatim = 0 self.body.append("\n\\end{verbatim}\n") def anydesc_title(self, title): """Returns the title for xxxdesc environments.""" if self.in_anydesc in ('ctypedesc','memberdesc','memberdescni',): # TODO [tag_or_type] {name} return '%s' % title elif self.in_anydesc in ('cvardesc','excclassdesc', 'funcdesc','funcdescni'): # "funcname(arguments)" to "{funcname}{arguments}" return '{'+title.replace('(','}{').replace(')','}') # 'datadesc','datadescni', 'excdesc','classdesc*','csimplemacrodesc' return "{%s}" % title def visit_title(self, node): title = node.astext() if self.in_anydesc: self.body.append(self.anydesc_title(title)) raise nodes.SkipNode title = self.remap_title.get(title, title) # TODO label_prefix might not be set yet. label = self.generate_section_label(title) section_name = self.d_class.section(self.section_level + 1) self.body.append("\n\n\\%s{" % section_name) self.context.append("\\label{%s}}\n" % label) self.in_title = True def depart_title(self, node): self.in_title = False self.body.append(self.context.pop()) def visit_target(self, node): pass def depart_target(self, node): pass def bookmark(self, node): pass def visit_definition(self, node): pass def depart_definition(self, node): pass def visit_reference(self, node): if node.has_key('refuri'): refuri = node['refuri'] basename = os.path.splitext(refuri)[0] label = self.label_prefix + "-" + self.refuri_override.get(basename, basename) print "got refuri=%r, label=%r" % (refuri, label) elif node.has_key('refid'): label = self.generate_section_label(node['refid']) print "got refid=%r, label=%r" % (node['refid'], label) else: print "warning: unhandled reference: node=%r" % node LaTeXTranslator.visit_reference(self, node) self.body.append("section~\\ref{%s}, " % label) raise nodes.SkipDeparture _quoted_phrase_re = re.compile(r'"([^"]+)"') _em_dash_re = re.compile(r'\s+\-\-\s+') def visit_Text(self, node): text = node.astext() if self.in_title: text = self.remap_title.get(text, text) if not (self.literal or self.verbatim): text = self._em_dash_re.sub(u"\u2014", text) text = self._quoted_phrase_re.sub(u"\u201C\\1\u201D", text) text = re.sub(r'\bdocument\b', "section", text) text = self.encode(text) # A couple of transformations are easiest if they go direct # to LaTeX, so do them *after* encode(). text = text.replace("UNIX", "\\UNIX{}") self.body.append(text) def depart_Text(self, node): pass # table handling # TODO move table handling into latex2e writer Table class. def visit_table(self, node): self.active_table.open() def depart_table(self, node): self.body.append('\\end{table%s}\n' % (self.roman[len(self.active_table._col_specs)]) ) # TODO use roman to map name ? only i ... iv is supported self.active_table.close() def visit_thead(self, node): self.body.append('\\begin{table%s}{l%s}{textrm}\n' % (self.roman[len(self.active_table._col_specs)], '|l'*(len(self.active_table._col_specs)-1) ) ) self.active_table.set('preamble written',1) def depart_thead(self, node): pass def visit_row(self, node): if not isinstance(node.parent, nodes.thead): self.body.append('\\line%s' % (self.roman[len(self.active_table._col_specs)], ) ) def depart_row(self, node): # CAUTION: latex2html stuffs content outside of {} into paragraphs # before the table. pass def visit_entry(self, node): if node.has_key('morerows') or node.has_key('morecols'): raise NotImplementedError('Cells spanning rows or columns are not' ' supported.') # CAUTION: latex2html needs ``\lineii{`` the brace must follow # immediately self.body.append('{') def depart_entry(self, node): self.body.append('}\n') def convert(infilename, outfilename): print "converting %s to %s" % (infilename, outfilename) pub = Publisher() pub.set_components('standalone', # reader 'restructuredtext', # parser 'latex') # writer (arg, will be discarded) pub.reader = OptikReader() pub.writer = PyLaTeXWriter() pub.process_programmatic_settings(None, None, None) pub.set_source(source_path=infilename) pub.set_destination(destination_path=outfilename) pub.publish() def main(): convert(sys.argv[1], sys.argv[2]) if missing: mod = open("missing.py", "w") mod.write("# possible markups:\n") mod.write("# module, code, method, class, function, member, var. Are there more?\n") mod.write("codemarkup = {\n") keys = sorted(missing) for name in keys: mod.write(" '%s': 'code',\n" % name) mod.write("}\n") mod.close() main() |
From: Thomas H. <th...@us...> - 2006-05-26 10:29:07
|
Update of /cvsroot/ctypes/ctypes/docs/manual In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv16161 Modified Files: reference.txt Log Message: Fresh start on the ctypes-reference. Index: reference.txt =================================================================== RCS file: /cvsroot/ctypes/ctypes/docs/manual/reference.txt,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** reference.txt 24 Mar 2006 21:03:22 -0000 1.2 --- reference.txt 26 May 2006 10:29:03 -0000 1.3 *************** *** 1,746 **** ! ctypes manual ! +++++++++++++ ! ! ! Shared Libraries, DLLs ! ---------------------- ! ! Shared libraries are accessed when compiling/linking a program, and ! when the program is run. The purpose of the ``find`` method is to ! locate a library in a way similar to what the compiler does (on ! platforms with several versions of a shared library the most recent ! should be loaded), while ``load`` acts like when a program is run, and ! uses the runtime loader directly. ``load_version`` works like ``load`` ! but tries to be platform independent (for cases where this makes ! sense). Loading via attribute access is a shorthand notation ! especially usefull for interactive use, it is equivalent to calling ! ``load_version`` with no version specified. ! ! ! class LibraryLoader ! ................... ! ! Instances of ``LibraryLoader`` are used to load shared libraries. ! Usually there is no need to create a libraryloader, instead one of the ! predefined loaders should be used. ! ! Libraryloaders have the following methods: ! ! ``find(name, mode=None)`` ! ! Try to find a library, load and return it. ``name`` is the ! library name without any prefix like ``lib``, suffix like ``.so``, ! ``.dylib`` or version number (this is the form used for the posix ! linker option ``-l``). ! ! ``mode`` allows to override the default flags passed to the ! ``dlopen()`` function, ignored on Windows. ! ! On Windows, this method does exactly the same as the ``load`` ! method. ! ! On other platforms, this function might call other programs like ! the compiler to find the library. When using ctypes to write a ! shared library wrapping, consider using ``load_version`` or ! ``load`` instead. ! ! ``load_version(name, version=None, mode=None)`` ! ! Build a system dependent filename from ``name`` and optionally ! ``version``, then load and return it. ``name`` is the library ! name without any prefix like ``lib`` and suffix like ``.so`` or ! ``.dylib``. This method should be used if a library is available ! on different platforms, using the particular naming convention of ! each platform. ! ! ``mode`` allows to override the default flags passed to the ! ``dlopen()`` function, ignored on Windows. ! ! Example: calling ``loader.load_version('z', '1.1.3')`` would ! possibly load ``/usr/lib/libz.1.1.3.dylib`` on Mac OS X, or ! ``/lib/libz.so.1.1.3`` on a Linux system. ! ! ``load(libname, mode=None)`` ! ! Load and return the library with the given libname. On most ! systems ``libname`` is the filename of the shared library; when ! it's not a pathname it will be searched in a system dependent list ! of locations (on many systems additional search paths can be ! specified by an environment variable). Sometimes the file ! extension (like ``.dll`` on Windows) can be omitted. ! ! ``mode`` allows to override the default flags passed to the ! ``dlopen()`` function. ``RTLD_LOCAL`` and ``RTLD_GLOBAL`` are ! typical values. On Windows, ``mode`` is ignored. ! ! ``load_library(pathname, mode=None`` ! ! Load and return the library with the given pathname. This method ! passes the ``pathname`` directly to the underlying ``dlopen`` or ! ``LoadLibrary`` function. ! ! ``mode`` allows to override the default flags passed to the ! ``dlopen()`` function. ``RTLD_LOCAL`` and ``RTLD_GLOBAL`` are ! typical values. On Windows, ``mode`` is ignored. ! ! ``LoadLibrary(pathname, mode=None)`` ! ! This is an alias for the ``load_library`` method documented above, ! maintained for backwards comatibility only. ! ! ! Libaries can also be loaded by accessing them as attributes of the ! loader instance, internally this calls ``load_version`` without ! specifying ``version`` or ``mode``. Obviously this only works for ! libraries with names that are valid Python identifiers, and when the ! name does not start with a ``_`` character. ! ! Predefined library loaders ! .......................... ! ! ctypes provides some LibraryLoader instances, the differences between ! them are the calling conventions the functions will use and the ! default return type of the functions. All these loaders use the ! ``RTLD_LOCAL`` mode flag. ! ! Functions can be accessed as named attributes of loaded libraries. ! ! On Windows, structured exception handling is used around the function ! call to protect Python from crashing in case you pass invalid ! parameters to the function. ``cdll`` ! ! Functions provided by libraries loaded using the ``cdll`` loader ! will be called with the standard C calling convention, and have a ! default return type of ``int``. ctypes releases the Python global ! interpreter lock (GIL) just before calling the foreign function, ! and reacquires it before returing, so other threads are able to ! run. ! ! ``windll`` ! ! Windows only. Functions provided by libraries loaded by ! ``windll`` will be called using the Windows ``__stdcall`` calling ! convention. ctypes can detect when the wrong number ! of parameters has been passed to the function call by examining ! the stack pointer before and after the function call. If the ! wrong parameter count was used, an exception is raised (although ! the function really *has* been called). The return value of the ! function is lost in this case. Again, the GIL is released during ! the duration of the function call. ! ``oledll`` ! ! Windows only. ``oledll`` behaves in the same way as ``windll``, ! except that the called function is expected to return a ! ``HRESULT`` value. These are long values containing error or ! success codes. In case the function returns an error ``HRESULT`` ! value, a ``WindowsError`` is raised. The GIL is released during the ! duration of function call. ! ``pydll`` ! ! This loader allows to call functions in libraries using the ! *Python* calling convention, for example Python C API functions. ! The GIL is *not* released during the function call, and the state ! of the Python error flag is examined after the function returns. ! If the error flag is set, the Python exception is raised. ! ! ctypes provides a prefabricated instance of ``pydll`` exposing the ! Python C api as the ``pythonapi`` symbol, you should however make ! sure to set the correct ``restype`` for the functions you use. ! ! Library objects ! ............... ! ! The library loaders create instances of ``CDLL``, ``WinDLL``, ! ``OleDLL``, or ``PyDLL`` classes. You can, however, also load a ! library by constructing one of these classes by calling the ! constructor with the pathname of the library and an optional ``mode`` ! argument as described in the previous section. ! ! Library objects implement ``__getattr__`` and ``__getitem__`` methods ! that allow to access foreign functions by attribute access or ! indexing. The latter is useful if the name of the function is not a ! valid Python identifier, or clashes with special Python method names ! that start and end with two underscore characters. ! ! Library objects have two private attributes: ``_name`` is the pathname ! of the library, ``_handle`` is the handle to the library that ! ``dlopen`` has returned. ! ! ! Foreign functions ! ----------------- ! ! Functions exported from loaded shared libraries (foreign functions) ! can be accessed in two ways. The easiest way is to retrieve them as ! attributes of library objects by name:: ! ! libc = cdll.find("c") # posix ! libc = cdll.msvcrt # windows ! # attribute access ! atoi = libc.atoi ! # alternative indexing notation ! atoi = libc["atoi"] ! ! This creates an instance of a foreign function object, using the ! calling convention specified by the library object ``cdll``, bound to ! the C library ``atoi`` function. The C function is assumed to return ! an integer (which is correct for ``atoi``), and the argument types are ! not specified (``atoi`` expects a single ``char *`` argument). ! ! If the library function returns a type different from ``int``, the ! ``restype`` attribute can be set to a ctypes type that describes the ! return type, or to ``None`` meaning no return value (``void``). ! ! The optional ``argtypes`` attribute can be set to a sequence of ctypes ! types that the function expects. ! ! If needed, the function can (as in C) be called with more arguments ! than the length of the argtypes sequence. ! ! The optional ``errcheck`` attribute can be set to a Python callable, ! which can be used to validate and/or process the library function's return ! value. ``errcheck`` will be called with three arguments, after the ! library function has returned:: ! ! errcheck(retval, function, arguments) ! ! ``retval`` is the value that the library function returned, converted ! according to ``restype``. ``function`` is the ctypes function object ! (libc.atoi in this case), and ``arguments`` is a tuple containing the ! arguments that have been used to call ``function``. ``errcheck`` ! should validate the library function result, raise an error if it ! detects a failure, or return the needed return value otherwise. ! ! Function prototypes ! ................... ! ! Another way to access a function exported from shared libraries is to ! first create a prototype by calling a factory function, specifying the ! return type and the argument types. The factory function itself ! specifies the calling convention: ``CFUNCTYPE`` uses the standard C ! calling convention, ``WINFUNCTYPE`` (Windows only) uses the stdcall ! calling convention. The factory function must be called with the ! return type plus the argument types. For the C ``atoi`` function one ! would use ``CFUNCTYPE(c_int, c_char_p)``. ! ! This returns a function prototype, which is a ctypes type representing ! all functions that are compatible with the calling convention, return ! type, and argument types. ! ! The ``CFUNCTYPE`` and ``WINFUNCTYPE`` factory functions cache and ! reuse the types they create in internal caches, so is is cheap to call ! them over and over with the same or different arguments. ! ! An instance of this function prototype, bound to a foreign library ! function, can be created by calling the prototype with the name of the ! function as string, and a loaded library:: ! ! proto = CFUNCTYPE(c_int, c_char_p) ! atoi = proto("atoi", libc) ! ! Parameter flags ! ............... ! ! It is possible to specify a third argument ``paramflags`` when calling ! the prototype. This is used to specify additional information for ! each argument: direction of data transfer, the name, and a default ! value. ! ! A tuple with the same length as ``argtypes`` (the second argument in ! the prototype call) must be used. Each item in this tuple must be a ! tuple, having either one, two, or three items. ! ! The first item is the direction flag, an integer specifying if this is ! an input (use ``1``) or an output (use ``2``) parameter. The optional ! second item is a string containing the parameter name, the optional ! third item is a default value for the parameter. ! ! If parameter names are specified, the function object created can be ! called with named arguments in the usual way. Arguments with default ! values do not need to be specified when the function is called. ! ! ``out`` parameter types must be pointer types. When the function ! object is called, ctypes will automatically create empty instances of ! them, pass them to the library function, retrieve the value from them, ! and return the value, if there is exactly one ``out`` parameter, or a ! tuple of values, if there is more than one ``out`` parameter. The ! original foreign function return value is lost in this case (but see ! below for how it can be retrieved). ! ! If ``paramflags`` have been used in the prototype call, and an ! ``errcheck`` attribute is also present, the ``errcheck`` callable will ! be called with a fourth parameter ``outargs``:: ! ! errcheck(retval, function, arguments, outargs) ! ! ``outargs`` is a tuple containing all the ``out`` parameters that ! ctypes has created. Without the ``errcheck`` function ctypes would ! retrieve the values contained in these pointer objects, and return ! them. The ``errcheck`` function can let ctypes continue this ! processing by returning the ``outargs`` tuple. It could also return ! something else, or raise an error if it detects that the library ! function has failed. ! ! Callback functions ! .................. ! ! ctypes is able to create C callable functions from Python callables. ! This is useful because sometimes library functions need a callback ! function parameter; the ``qsort`` C function is such an example. ! ! Callback functions are created by first creating a function prototype ! with a call to ``CFUNCTYPE`` or ``WINFUNCTYPE``, specifying the return ! type and the argument types that the callback function will receive. ! ! Calling the prototype with a single Python callable will create and ! return a C-callable function pointer or callback function. Note that ! this allows using prototypes as decorators creating callback ! functions (Windows example):: ! ! @WINFUNCTYPE(BOOL, HWND, LPARAM) ! def enumwindowsproc(hwnd, lParam): ! .... ! return True ! ! When a Python exception is raised in the Python callable, the return ! value of the C callable function is undefined. ! ! Important note: You must keep a reference to the callback AS LONG as ! foreign code will call it! Segfaults will result if the callback is ! cleaned up by Python's garbage collector and external code then ! tries to call it. ! ! Callback objects can also be called from Python - this may be useful ! for debugging. ! ! ! COM methods (Windows only) ! .......................... ! ! XXX Should this be left undocumented? Mentioned for completeness. ! ! The prototypes created by ``WINFUNCTYPE`` can be called with a ! positive small integer ``index``, a string ``name``, an optional ! ``paramflags`` tuple, and a optional ``iid`` parameter. ! ! This creates a function object wrapping a COM method. ``index`` is ! the index into the COM object's virtual function table, ``name`` is ! the name of the COM method (only useful for debugging), ``paramflags`` ! has the same meaning as for normal function objects, and ``iid`` is a ! string or buffer containing the interface id of the COM interface ! this method belongs to. ``iid`` is used to get extended COM error ! information in case the method returns a FAILED ''HRESULT`` value. ! ! Note that COM methods expect an additional first argument that is NOT ! listed in the prototypes ``argtypes`` when they are called: this must ! be the integer address of a COM interface pointer. ! ! ! Simple types ! ------------ ! ! Simple types have some special behaviour: When they are accessed as ! structure or union fields, items of array instances, or as foreign ! function return values, they are transparently converted from and to ! the native Python types int, long, string, and unicode. ! ! This is *not* the case for subclasses of simple data types, so while a ! ``c_void_p`` type is transparently converted from and to Python ! integer or long, a subclass of c_void_p is *not* converted. This ! allows you to define new behaviour almost completely. ! ! Class attributes of simple types ! ................................ ! ! ``__ctype__be__``, ``__ctype_le__`` ! ! If the type supports different byte order (pointer types do NOT ! support this), ``__ctype_be__`` and ``__ctype_le__`` are types ! with bug endian and little endian byte order. For example, ! ``c_int.__ctype_be__`` is an integer type with the memory block in ! big endian byte order. ! ! ``_type_`` ! ! Implementation artifact: the typecode for this type, a single ! character string code compatible to what the ``struct`` module uses. ! Additional characters are used for types that the ``struct`` module ! does not support. ! ! ! Class methods of simple types ! ............................. ! ! (To be exact, these are not class methods, instead these are methods ! of the metaclass. The most prominent difference to classmethods is ! that you can call these methods on the class, but not on the instance ! of the simple type.) ! ! ``__ctypes_from_outparam__`` ! ! TBD ! ! ``from_address`` ! ! TBD ! ! ``from_param`` ! ! This class method is used to adapt function parameters. If a type ! is specified in a function's argtypes sequence, in a function call ! the ``from_param(arg)`` method will be called with the actual ! argument, and the result will be passed to the foreign function ! call as a parameter. ! ! ``from_param`` usually returns an internal object that you cannot ! use in Python code - it only makes sense to pass this object to ! foreign functions. ! ! On one hand, ``from_param`` is a performance optimization - it ! allows you to pass Python integers to function calls expecting a ! ``c_int`` argument type, without having to create a full-featured ! ``c_int`` instance. ! ! On the other hand, ``from_param`` can adapt other objects to ! parameters. XXX explain the automatic ``byref`` call for byref ! arguments. ! ! ``in_dll`` ! ! TBD ! ! Instance attributes of simple types ! ................................... ! ! ``value`` ! ! Allows to get or set the current value of the object. For simple ! types, this is always a native Python object like integer, long, ! string, unicode, or None. ! ! ``_objects`` (never modify this) ! ! Implementation artifact: a Python object keeping references to ! other objects which must be kept alive. Never modify anything on ! the returned object. XXX Should probably not be exposed. ! ! ``_b_base_`` (readonly) ! ! Implementation artifact: the base object owning the memory block ! (if any). ! ! ``_b_needsfree_`` (readonly) ! ! Implementation artifact: does this object have to free its memory ! block on destruction. ! ! ``_as_parameter_`` (readonly) ! ! Implementation artifact (?): how to pass this object as a function ! parameter. ! ! ! Numeric types ! ............. ! ! Integer types are ``c_byte``, ``c_short``, ``c_int``, ``c_long``, ! ``c_longlong`` and their unsigned variants ``c_ubyte``, ``c_ushort``, ! ``c_uint``, ``c_ulong`` and ``c_ulonglong``, floating point types are ! ``c_float`` and ``c_double``. ! ! The constructor and the ``from_param`` class method accept a Python ! integer for integer types, a Python float for floating point types. ! ! On 32-bit platforms where sizeof(int) == sizeof(long), ``c_int`` is an ! alias for ``c_long``, on 64-bit platforms where sizeof(long) == ! sizeof(long long), ``c_long`` is an alias for ``c_longlong``. ! ! Character types ! ............... ! ! Character types are ``c_char`` and ``c_wchar``, representing the C ! ``char`` and ``wchar_t`` types. ! ! The constructor and the ``from_param`` class method accept a single ! character Python string or unicode string. Conversion between string ! and unicode, if needed, is done according to the ctypes ! encoding/decoding rules. ! ! ! Pointer types ! ............. ! ! The only simple pointer type is ``c_void_p``, which represents the C ! ``void *`` data type. ``c_void_p`` can also be written as ! ``POINTER(None)``. ! ! The constructor accepts one optional argument, which must be an ! integer or long (interpreted as an address), or ``None``. ! ! The ``from_param`` class method accepts everything that could be used ! as a pointer. XXX Should accept objects using the buffer interface as ! well. ! ! The ``value`` attribute accepts and returns None or integer. ! ! XXX Shouldn't the constructor accept the same types as from_param? ! ! ! String types ! ............ ! ! ctypes has the ``c_char_p`` and ``c_wchar_p`` types which represent ! const pointers to zero terminated strings in C: ``const char *`` and ! ``const wchar_t *``. Since strings and Unicode instances are ! immutable, these types should be considered readonly: do not pass them ! to functions that write into the buffer. ! ! The constructor accepts one optional argument, which must be a Python ! or unicode string, an integer, or ``None``. ! ! The ``from_param`` class method accepts a string or a Unicode string, ! as well as ``None``. Conversion between string and Unicode, if ! needed, is done according to the ctypes encoding/decoding rules. ! ! XXX Why does the constructor accept an integer, and from_param doesn't? ! ! Structure and union types ! ------------------------- ! ! ctypes provides the abstract base classes ``Structure`` and ``Union`` ! to define structure and union types. Subclasses must at least define ! a ``_fields_`` attribute. ! ! Defining field names and types ! .............................. ! ! ``_fields_`` must be a sequence of tuples. The first item of each ! tuple is a string specifying the name of the structure/union field. ! The second item must by a ctypes type. ! ! A descriptor will be created for each field, allowing you to access the ! field's contents from instances. Accessed from the class, the fields ! expose readonly ``.offset`` and ``.size`` attributes. ``offset`` is ! the byte-offset of the field from the beginning of the ! structure/union, ``size`` is the number of bytes the field contains. ! ! A simple example is a POINT structure containing integer fields named ! ``x`` and ``y``:: ! ! class Point(Structure): ! _fields_ = [("x", c_int), ! ("y", c_int)] ! ! ! ! Field alignment ! ............... ! ! Normally fields are aligned in the same way as the host's C compiler ! would do it. This native alignment can be overridden by setting a ! ``_pack_`` attribute in the type. It must be a small positive integer ! which is the maximum field alignment. ! ! Bit fields ! .......... ! ! Integer fields support bit sizes. The bit-size must be specified as ! the third item of the ``_fields_`` tuple. Bit fields are constructed ! in the same way the host's C compiler does it. For bit fields, the ! field descriptor's ``.size`` attribute contains the number of bits in ! the high word, and the bit offset from the beginning of the structure in ! the low word. XXX is that correct? ! ! Recursive data types ! .................... ! ! To define recursive types, it is possible to assign the ``_fields_`` ! value *after* the class statement. Here is an example of a linked ! list data structure, which contains a pointer to itself:: ! ! class Node(Structure): ! pass ! Node._fields_ = [("next", POINTER(Node)), ! ("value", ...)] ! ! ``_fields_`` must be set, and cannot be changed, after the type is ! used for the first time. ! ! Byte order ! .......... ! ! It is possible to create Structure and Union types using non-native ! byte order by using the ``BigEndianStructure``, ! ``LittleEndianStructure``, ``BigEndianUnion``, and ! ``LittleEndianUnion`` base classes. Structures and Unions with ! non-native byte order do *not* support pointer fields. ! ! ! Builtin functions ! ----------------- ! ! ``addressof(object)`` ! ! Returns the address of a ctypes instance as an integer. ! ! ``alignment(type_or_object)`` ! ! Returns the alignment requirements in bytes of a ctypes type or ! instance. ! ! ``byref(object)`` ! ! Returns a light-weight pointer to a ctypes instance. The returned ! object can only be used as function call parameter. Behaves the ! same as calling ``pointer(object)``, but is a lot faster. Same as ! ``&object`` in C. ! ! ``cast(object, typ)`` ! ! This function is similar to the cast operator in C. Returns a new ! instance of ``type`` which shares the memory block of ``object``. ! ``typ`` must be a pointer type. ! ! ``CFUNCTYPE(restype, *argtypes)`` ! ! Create a function prototype using the C calling convention. ! ! ! ``create_string_buffer(init, size=None)`` ! ! Convenience function to create a mutable character buffer. ! ! ``init`` must be a string. If ``size`` is supplied it must be a ! positive integer that specifies the size of the buffer, otherwise ! the length of the ``init`` string is used. ! This function returns a ctypes array of characters ``c_char``. ! ! ``create_unicode_buffer(init, size=None)`` ! ! Convenience function to create a mutable unicode buffer. ! ! ``init`` must be a unicode string. If ``size`` is supplied it ! must be a positive integer that specifies the number of characters ! in the buffer, otherwise the length of the ``init`` string is ! used. This function returns a ctypes array of characters ``c_wchar``. ! ! ! ``DllCanUnloadNow()``, ``DllGetClassObject(rclsid, riid, ppv)`` (Windows only) ! ! Functions used to implement COM servers. ! ! ! ``FormatError([code])`` (Windows only) ! ! Returns a textual description of the error code, or the last error ! code set by Windows. ! ! ``GetLastError()`` (Windows only) ! ! Returns the last error code set by Windows. ! ! ``memmove(dst, src, count)`` ! ! Same as the standard C ``memmove`` library function: copies ! ``count`` bytes from ``src`` to ``dst``. ``dst`` and ``src`` must ! be integers or anything else that can be converted into a pointer. ! ! ``memset(dst, c, count)`` ! ! Same as the standard C ``memset`` function. Fills the memory block ! at address ``dst`` with ``count`` bytes of value ``c``. ``dst`` must be ! an integer specifying an address, or a ctypes instance. ! ! ! ``pointer(object)`` ! ! This function creates a new pointer instance, pointing to the ! supplied argument which must be an instance of a ctypes type. The ! return pointer is of type ``POINTER(type(object))``. If you have ! a ctypes instance, and you want to pass the address of it to a ! function call, you should use ``byref(object)`` instead which is ! much faster. ! ! NULL pointer instances are boolean``False``, so to check for a ! NULL pointer do this:: ! ! # assuming ptr is in ctypes pointer instance ! if ptr: ! print "Non-NULL pointer instance" ! else: ! print "NULL pointer instance" ! ! ! ``POINTER(cls)`` ! ! This factory function creates and returns a new ctypes type. ! Pointer types are cached, so calling this function is cheap. ! ! To create a ``NULL`` pointer instance, call the created type ! without an argument:: ! ! null_ptr = POINTER(c_int)() ! ! ! ``set_conversion_mode(encoding, errors)`` ! ! This function sets the encoding/decoding rules which are used when ! ctypes has to convert between unicode and byte strings. It ! returns the previous encoding, as well as a tuple of any errors. ! If not set, default conversions are used: ! On Windows, ``msbc, ignore`` , on other systems, ``ascii, strict``. ! ! ! ``sizeof(type_or_object)`` ! ! Returns the size in bytes of a ctypes type or instance memory ! buffer. Does the same as the C sizeof() function. ! ! ! ``string_at(addr[, size])`` ! ! This function does the same as the Python ``PyString_FromString`` / ! ``PyString_FromStringAndSize`` C api functions. ! ! ``WinError(code=None, descr=None)`` ! ! XXX This is probably the worst named thing in ctypes! ! ! This function creates a ``WindowsError`` instance. If ``code`` is ! not specified, GetLastError() is called to determine the error ! code. If ``descr`` is not specified, ``FormatError`` is called to ! get a textual description of the error. ! ! ``WINFUNCTYPE(restype, *argtypes)`` (Windows only) ! ! Create a function prototype using the __stdcall calling convention ! (on Windows), or using the C calling convention (on Windows CE). ! ! ``wstring_at(addr[, size])`` ! ! This function does the same as the Python ``PyUnicode_FromWideString`` ! C api function. If ``size`` is not specified, ``wcslen`` is used ! to determine the string length. ! ! ! Deprecated functions ! .................... ! ! These deprecated functions are still supported for backwards ! comatibility, they should not be used for new code: ! ! ``c_buffer(init, size=None)`` ! ! Deprecated. Use ``create_string_buffer()`` instead. ! ! ``ARRAY(cls, len)`` ! ! Deprecated. Use ``cls * len`` instead. ! ! ``SetPointerType(pointer_class, cls)`` ! ! Deprecated. --- 1,76 ---- ! ctypes reference ! ================ + ``ARRAY`` + ``ArgumentError`` + ``Array`` + ``BigEndianStructure`` + ``CDLL`` + ``CFUNCTYPE`` + ``DllCanUnloadNow`` + ``DllGetClassObject`` + ``FormatError`` + ``GetLastError`` + ``HRESULT`` + ``LibraryLoader`` + ``LittleEndianStructure`` + ``OleDLL`` + ``POINTER`` + ``PYFUNCTYPE`` + ``PyDLL`` + ``RTLD_GLOBAL`` + ``RTLD_LOCAL`` + ``SetPointerType`` + ``Structure`` + ``Union`` + ``WINFUNCTYPE`` + ``WinDLL`` + ``WinError`` + ``addressof`` + ``alignment`` + ``byref`` + ``c_buffer`` + ``c_byte`` + ``c_char`` + ``c_char_p`` + ``c_double`` + ``c_float`` + ``c_int`` + ``c_int16`` + ``c_int32`` + ``c_int64`` + ``c_int8`` + ``c_long`` + ``c_longlong`` + ``c_short`` + ``c_size_t`` + ``c_ubyte`` + ``c_uint`` + ``c_uint16`` + ``c_uint32`` + ``c_uint64`` + ``c_uint8`` + ``c_ulong`` + ``c_ulonglong`` + ``c_ushort`` + ``c_void_p`` + ``c_voidp`` + ``c_wchar`` + ``c_wchar_p`` + ``cast`` ``cdll`` ! ``create_string_buffer`` ! ``create_unicode_buffer`` ! ``memmove`` ! ``memset`` ``oledll`` ! ``pointer`` ! ``py_object`` ``pydll`` ! ``pythonapi`` ! ``resize`` ! ``set_conversion_mode`` ! ``sizeof`` ! ``string_at`` ! ``windll`` ! ``wstring_at`` |
From: Thomas H. <th...@us...> - 2006-05-26 10:28:47
|
Update of /cvsroot/ctypes/ctypes/docs/manual In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv15962 Modified Files: tutorial.txt Log Message: Header goes in top-level file 'ctypes.tex'. Index: tutorial.txt =================================================================== RCS file: /cvsroot/ctypes/ctypes/docs/manual/tutorial.txt,v retrieving revision 1.29 retrieving revision 1.30 diff -C2 -d -r1.29 -r1.30 *** tutorial.txt 26 May 2006 09:02:38 -0000 1.29 --- tutorial.txt 26 May 2006 10:28:33 -0000 1.30 *************** *** 1,4 **** - ``ctypes`` is a foreign function library for Python. - ctypes tutorial =============== --- 1,2 ---- |
From: Thomas H. <th...@us...> - 2006-05-26 10:27:59
|
Update of /cvsroot/ctypes/ctypes/docs/manual In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv15617 Added Files: ctypes.txt Log Message: Top-level file for the docs. --- NEW FILE: ctypes.txt --- ``ctypes`` is a foreign function library for Python. .. include:: tutorial.txt .. include:: reference.txt |
From: Thomas H. <th...@us...> - 2006-05-26 09:02:43
|
Update of /cvsroot/ctypes/ctypes/docs/manual In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv17589 Modified Files: tutorial.txt Log Message: Minor updates. Index: tutorial.txt =================================================================== RCS file: /cvsroot/ctypes/ctypes/docs/manual/tutorial.txt,v retrieving revision 1.28 retrieving revision 1.29 diff -C2 -d -r1.28 -r1.29 *** tutorial.txt 19 May 2006 18:30:31 -0000 1.28 --- tutorial.txt 26 May 2006 09:02:38 -0000 1.29 *************** *** 641,660 **** -------- Pointer instances are created by calling the ``pointer`` function on a ``ctypes`` type:: ! >>> from ctypes import * ! >>> i = c_int(42) ! >>> pi = pointer(i) ! >>> ! ! XXX XXX Not correct: use indexing, not the contents atribute Pointer instances have a ``contents`` attribute which returns the ! ctypes' type pointed to, the ``c_int(42)`` in the above case:: ! >>> pi.contents ! c_long(42) ! >>> Assigning another ``c_int`` instance to the pointer's contents --- 641,672 ---- -------- + XXX Rewrite this section. Normally one only uses indexing, not the .contents + attribute! + List some recipes with pointers. bool(ptr), POINTER(tp)(), ...? + Pointer instances are created by calling the ``pointer`` function on a ``ctypes`` type:: ! >>> from ctypes import * ! >>> i = c_int(42) ! >>> pi = pointer(i) ! >>> Pointer instances have a ``contents`` attribute which returns the ! object to which the pointer points, the ``i`` object above:: ! >>> pi.contents ! c_long(42) ! >>> ! ! Note that ``ctypes`` does not have OOR (original object return), it ! constructs a new, equivalent object each time you retrieve an ! attribute:: ! ! >>> pi.contents is i ! False ! >>> pi.contents is pi.contents ! False ! >>> Assigning another ``c_int`` instance to the pointer's contents *************** *** 662,692 **** where this is stored:: ! >>> pi.contents = c_int(99) ! >>> pi.contents ! c_long(99) ! >>> Pointer instances can also be indexed with integers:: ! >>> pi[0] ! 99 ! >>> - XXX What is this??? Assigning to an integer index changes the pointed to value:: ! >>> i2 = pi[0] ! >>> i2 ! 99 ! >>> pi[0] = 22 ! >>> i2 ! 99 ! >>> It is also possible to use indexes different from 0, but you must know ! what you're doing when you use this: You access or change arbitrary ! memory locations when you do this. Generally you only use this feature ! if you receive a pointer from a C function, and you *know* that the ! pointer actually points to an array instead of a single item. Pointer classes/types --- 674,702 ---- where this is stored:: ! >>> pi.contents = c_int(99) ! >>> pi.contents ! c_long(99) ! >>> Pointer instances can also be indexed with integers:: ! >>> pi[0] ! 99 ! >>> Assigning to an integer index changes the pointed to value:: ! >>> print i ! c_long(99) ! >>> pi[0] = 22 ! >>> print i ! c_long(22) ! >>> It is also possible to use indexes different from 0, but you must know ! what you're doing, just as in C: You can access or change arbitrary ! memory locations. Generally you only use this feature if you receive a ! pointer from a C function, and you *know* that the pointer actually ! points to an array instead of a single item. Pointer classes/types *************** *** 1175,1179 **** 2 >>> resize(short_array, 32) ! >>> sizeof(short_array) 32 >>> sizeof(type(short_array)) --- 1185,1189 ---- 2 >>> resize(short_array, 32) ! >>> sizeof(short_array) 32 >>> sizeof(type(short_array)) |
From: Thomas H. <th...@us...> - 2006-05-23 20:27:48
|
Update of /cvsroot/ctypes/ctypes/ctypes In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv1048 Modified Files: __init__.py Log Message: Remove unneeded import. Index: __init__.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/ctypes/__init__.py,v retrieving revision 1.91 retrieving revision 1.92 diff -C2 -d -r1.91 -r1.92 *** __init__.py 23 May 2006 18:27:57 -0000 1.91 --- __init__.py 23 May 2006 20:27:36 -0000 1.92 *************** *** 2,6 **** import os as _os, sys as _sys - from itertools import chain as _chain # special developer support to use ctypes from the CVS sandbox, --- 2,5 ---- |
From: Thomas H. <th...@us...> - 2006-05-23 20:13:34
|
Update of /cvsroot/ctypes/ctypes In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv28165 Modified Files: ChangeLog Log Message: Index: ChangeLog =================================================================== RCS file: /cvsroot/ctypes/ctypes/ChangeLog,v retrieving revision 1.132 retrieving revision 1.133 diff -C2 -d -r1.132 -r1.133 *** ChangeLog 23 May 2006 19:45:36 -0000 1.132 --- ChangeLog 23 May 2006 20:13:26 -0000 1.133 *************** *** 25,29 **** signed and unsigned values. ! * source\_ctypes.c: Correct recount issues in the (unlikely) case that KeepRef fails. --- 25,29 ---- signed and unsigned values. ! * source\_ctypes.c: Correct refcount issues in the (unlikely) case that KeepRef fails. |
From: Thomas H. <th...@us...> - 2006-05-23 20:05:56
|
Update of /cvsroot/ctypes/ctypes/ctypes/test In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv25308/ctypes/test Modified Files: test_slicing.py Log Message: Oops, free'd the wrong pointer. Index: test_slicing.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/ctypes/test/test_slicing.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** test_slicing.py 23 May 2006 19:42:30 -0000 1.5 --- test_slicing.py 23 May 2006 20:05:41 -0000 1.6 *************** *** 64,68 **** def errcheck(result, func, args): retval = result.value ! dll.my_free(retval) return retval --- 64,68 ---- def errcheck(result, func, args): retval = result.value ! dll.my_free(result) return retval |
From: Thomas H. <th...@us...> - 2006-05-23 19:46:10
|
Update of /cvsroot/ctypes/ctypes In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv18106 Modified Files: ChangeLog Log Message: Index: ChangeLog =================================================================== RCS file: /cvsroot/ctypes/ctypes/ChangeLog,v retrieving revision 1.131 retrieving revision 1.132 diff -C2 -d -r1.131 -r1.132 *** ChangeLog 19 May 2006 19:24:54 -0000 1.131 --- ChangeLog 23 May 2006 19:45:36 -0000 1.132 *************** *** 1,2 **** --- 1,8 ---- + 2006-05-23 Thomas Heller <th...@py...> + + * ctypes\__init__.py: Fixed a possible FutureWarning when id() + returned an integer less than zero or larger than sys.maxint, in + CDLL.__repr__. + 2006-05-19 Thomas Heller <th...@py...> |
From: Thomas H. <th...@us...> - 2006-05-23 19:42:44
|
Update of /cvsroot/ctypes/ctypes/ctypes/test In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv16834 Modified Files: test_slicing.py Log Message: Another test which calls free on a string returned from a foreign function call. Index: test_slicing.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/ctypes/test/test_slicing.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** test_slicing.py 12 May 2006 20:06:09 -0000 1.4 --- test_slicing.py 23 May 2006 19:42:30 -0000 1.5 *************** *** 36,40 **** def test_char_ptr(self): ! s = "abcdefghijklmnopqrstuvwxyz\0" dll = CDLL(_ctypes_test.__file__) --- 36,40 ---- def test_char_ptr(self): ! s = "abcdefghijklmnopqrstuvwxyz" dll = CDLL(_ctypes_test.__file__) *************** *** 51,57 **** dll.my_strdup.restype = POINTER(c_byte) res = dll.my_strdup(s) ! self.failUnlessEqual(res[:len(s)-1], range(ord("a"), ord("z")+1)) dll.my_free(res) def test_char_array(self): s = "abcdefghijklmnopqrstuvwxyz\0" --- 51,79 ---- dll.my_strdup.restype = POINTER(c_byte) res = dll.my_strdup(s) ! self.failUnlessEqual(res[:len(s)], range(ord("a"), ord("z")+1)) dll.my_free(res) + def test_char_ptr_with_free(self): + dll = CDLL(_ctypes_test.__file__) + s = "abcdefghijklmnopqrstuvwxyz" + + class allocated_c_char_p(c_char_p): + pass + + dll.my_free.restype = None + def errcheck(result, func, args): + retval = result.value + dll.my_free(retval) + return retval + + dll.my_strdup.restype = allocated_c_char_p + dll.my_strdup.errcheck = errcheck + try: + res = dll.my_strdup(s) + self.failUnlessEqual(res, s) + finally: + del dll.my_strdup.errcheck + + def test_char_array(self): s = "abcdefghijklmnopqrstuvwxyz\0" |
From: Thomas H. <th...@us...> - 2006-05-23 18:28:06
|
Update of /cvsroot/ctypes/ctypes/ctypes In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv15628 Modified Files: __init__.py Log Message: Avoid FutureWarning in CDLL.__repr__ when id(self) is negative or larger than sys.maxint. Index: __init__.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/ctypes/__init__.py,v retrieving revision 1.90 retrieving revision 1.91 diff -C2 -d -r1.90 -r1.91 *** __init__.py 19 May 2006 20:06:36 -0000 1.90 --- __init__.py 23 May 2006 18:27:57 -0000 1.91 *************** *** 302,306 **** (self.__class__.__name__, self._name, (self._handle & (_sys.maxint*2 + 1)), ! id(self)) def __getattr__(self, name): --- 302,306 ---- (self.__class__.__name__, self._name, (self._handle & (_sys.maxint*2 + 1)), ! id(self) & (_sys.maxint*2 + 1)) def __getattr__(self, name): |
From: Thomas H. <th...@us...> - 2006-05-19 20:11:55
|
Update of /cvsroot/ctypes/ctypes In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv6668 Modified Files: MANIFEST.in Log Message: Include new files. Index: MANIFEST.in =================================================================== RCS file: /cvsroot/ctypes/ctypes/MANIFEST.in,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** MANIFEST.in 20 Apr 2006 17:53:44 -0000 1.14 --- MANIFEST.in 19 May 2006 20:11:52 -0000 1.15 *************** *** 1,4 **** # standard files ! include ACKS ANNOUNCE ChangeLog MANIFEST MANIFEST.in LICENSE.txt NEWS.txt README* # support files for development --- 1,4 ---- # standard files ! include ACKS ANNOUNCE BUGS ChangeLog MANIFEST MANIFEST.in LICENSE.txt NEWS.txt README* # support files for development *************** *** 26,29 **** --- 26,30 ---- # docs/manual + include docs/anatomy.txt include docs/manual/tutorial.txt include docs/manual/tutorial.html |
From: Thomas H. <th...@us...> - 2006-05-19 20:07:27
|
Update of /cvsroot/ctypes/ctypes/source In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv5193 Modified Files: _ctypes.c Log Message: Oops. Index: _ctypes.c =================================================================== RCS file: /cvsroot/ctypes/ctypes/source/_ctypes.c,v retrieving revision 1.330 retrieving revision 1.331 diff -C2 -d -r1.330 -r1.331 *** _ctypes.c 19 May 2006 20:05:42 -0000 1.330 --- _ctypes.c 19 May 2006 20:07:20 -0000 1.331 *************** *** 1826,1832 **** assert(sizeof(string) - 1 > sizeof(Py_ssize_t) * 2); #if (PY_VERSION_HEX < 0x02050000) - cp += sprintf(cp, "%zx", index); - #else cp += sprintf(cp, "%x", index); #endif while (target->b_base) { --- 1826,1832 ---- assert(sizeof(string) - 1 > sizeof(Py_ssize_t) * 2); #if (PY_VERSION_HEX < 0x02050000) cp += sprintf(cp, "%x", index); + #else + cp += sprintf(cp, "%zx", index); #endif while (target->b_base) { |
From: Thomas H. <th...@us...> - 2006-05-19 20:06:41
|
Update of /cvsroot/ctypes/ctypes/ctypes In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv4857 Modified Files: __init__.py Log Message: Change version to 0.9.9.7. Index: __init__.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/ctypes/__init__.py,v retrieving revision 1.89 retrieving revision 1.90 diff -C2 -d -r1.89 -r1.90 *** __init__.py 12 May 2006 20:26:04 -0000 1.89 --- __init__.py 19 May 2006 20:06:36 -0000 1.90 *************** *** 12,16 **** del _magicfile ! __version__ = "0.9.9.6" from _ctypes import Union, Structure, Array --- 12,16 ---- del _magicfile ! __version__ = "0.9.9.7" from _ctypes import Union, Structure, Array |
From: Thomas H. <th...@us...> - 2006-05-19 20:06:36
|
Update of /cvsroot/ctypes/ctypes In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv4842 Modified Files: setup.py Log Message: Change version to 0.9.9.7. Index: setup.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/setup.py,v retrieving revision 1.140 retrieving revision 1.141 diff -C2 -d -r1.140 -r1.141 *** setup.py 14 Apr 2006 15:49:33 -0000 1.140 --- setup.py 19 May 2006 20:06:31 -0000 1.141 *************** *** 12,16 **** LIBFFI_SOURCES='source/libffi' ! __version__ = "0.9.9.6" ################################################################ --- 12,16 ---- LIBFFI_SOURCES='source/libffi' ! __version__ = "0.9.9.7" ################################################################ |
From: Thomas H. <th...@us...> - 2006-05-19 20:05:52
|
Update of /cvsroot/ctypes/ctypes/source In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv4485 Modified Files: _ctypes.c Log Message: Fix some Py_ssize_t issues, change version to 0.9.9.7. Index: _ctypes.c =================================================================== RCS file: /cvsroot/ctypes/ctypes/source/_ctypes.c,v retrieving revision 1.329 retrieving revision 1.330 diff -C2 -d -r1.329 -r1.330 *** _ctypes.c 19 May 2006 19:21:01 -0000 1.329 --- _ctypes.c 19 May 2006 20:05:42 -0000 1.330 *************** *** 345,349 **** --- 345,353 ---- if (length < 0) return PyErr_Format(PyExc_ValueError, + #if (PY_VERSION_HEX < 0x02050000) "Array length must be >= 0, not %d", + #else + "Array length must be >= 0, not %zd", + #endif length); return CreateArrayType(self, length); *************** *** 1821,1825 **** --- 1825,1833 ---- assert(sizeof(string) - 1 > sizeof(Py_ssize_t) * 2); + #if (PY_VERSION_HEX < 0x02050000) + cp += sprintf(cp, "%zx", index); + #else cp += sprintf(cp, "%x", index); + #endif while (target->b_base) { bytes_left = sizeof(string) - (cp - string) - 1; *************** *** 1830,1834 **** --- 1838,1846 ---- return NULL; } + #if (PY_VERSION_HEX < 0x02050000) cp += sprintf(cp, ":%x", target->b_index); + #else + cp += sprintf(cp, ":%zx", target->b_index); + #endif target = target->b_base; } *************** *** 4621,4625 **** PyModule_AddObject(m, "FUNCFLAG_CDECL", PyInt_FromLong(FUNCFLAG_CDECL)); PyModule_AddObject(m, "FUNCFLAG_PYTHONAPI", PyInt_FromLong(FUNCFLAG_PYTHONAPI)); ! PyModule_AddStringConstant(m, "__version__", "0.9.9.6"); PyModule_AddObject(m, "_memmove_addr", PyLong_FromVoidPtr(memmove)); --- 4633,4637 ---- PyModule_AddObject(m, "FUNCFLAG_CDECL", PyInt_FromLong(FUNCFLAG_CDECL)); PyModule_AddObject(m, "FUNCFLAG_PYTHONAPI", PyInt_FromLong(FUNCFLAG_PYTHONAPI)); ! PyModule_AddStringConstant(m, "__version__", "0.9.9.7"); PyModule_AddObject(m, "_memmove_addr", PyLong_FromVoidPtr(memmove)); |
From: Thomas H. <th...@us...> - 2006-05-19 19:24:58
|
Update of /cvsroot/ctypes/ctypes In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv23001 Modified Files: ChangeLog Log Message: Index: ChangeLog =================================================================== RCS file: /cvsroot/ctypes/ctypes/ChangeLog,v retrieving revision 1.130 retrieving revision 1.131 diff -C2 -d -r1.130 -r1.131 *** ChangeLog 19 May 2006 19:22:37 -0000 1.130 --- ChangeLog 19 May 2006 19:24:54 -0000 1.131 *************** *** 1,4 **** --- 1,7 ---- 2006-05-19 Thomas Heller <th...@py...> + * docs\anatomy.txt: Add some documentation, also containing + doctest testcases, about some ctypes object internals. + * docs\manual\tutorial.txt: Document variable-sized data types. |
From: Thomas H. <th...@us...> - 2006-05-19 19:23:50
|
Update of /cvsroot/ctypes/ctypes/docs In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv22658 Added Files: test-anatomy.py anatomy.txt Log Message: Add (unfinished) description, also containing doctest testcases, about ctypes objects internals. --- NEW FILE: test-anatomy.py --- #!/usr/bin/env python import sys import doctest # handle platform specific issues WINDOWS = doctest.register_optionflag("WINDOWS") LINUX = doctest.register_optionflag("LINUX") SKIP = doctest.register_optionflag("SKIP") # handle size specific issues import ctypes c_int_name = ctypes.c_int.__name__ base = doctest.DocTestRunner class MyDocTestRunner(base): def run(self, test, compileflags=None, out=None, clear_globs=True): examples = test.examples[:] for ex in test.examples: if WINDOWS in ex.options and sys.platform != "win32": examples.remove(ex) elif LINUX in ex.options and not sys.platform.startswith("linux"): examples.remove(ex) elif SKIP in ex.options: examples.remove(ex) ## elif "printf(" in ex.source: ## # handle that doctest doesn't catch printf's output ## lines = ex.want.splitlines() ## try: ## int(lines[-1]) ## except ValueError: ## pass ## else: ## ex.want = "\n".join(lines[1:]) + "\n" ## else: ex.want = ex.want.replace("c_long", c_int_name) test.examples = examples return base.run(self, test, compileflags, out, clear_globs) doctest.DocTestRunner = MyDocTestRunner if __name__ == "__main__": # Python 2.5a2 formats exceptions differently than before, so we # add IGNORE_EXCEPTION_DETAIL. I do not know if this will be # fixed or not. doctest.testfile("anatomy.txt", optionflags=doctest.ELLIPSIS | doctest.IGNORE_EXCEPTION_DETAIL) --- NEW FILE: anatomy.txt --- ctypes objects anatomy ====================== This article describes some of the internals of ctypes types and ctypes instances. The object structure -------------------- Definition of the structure that each ctypes instance has:: struct tagCDataObject { PyObject_HEAD /* Standard Python object fields */ char *b_ptr; /* pointer to memory block */ int b_needsfree; /* does the object own its memory block? */ CDataObject *b_base; /* pointer to base object or NULL */ Py_ssize_t b_size; /* size of memory block in bytes */ Py_ssize_t b_length; /* number of fields of this object */ Py_ssize_t b_index; /* index of this object into the base objects b_object list */ PyObject *b_objects; /* references we need to keep */ union value b_value; /* a small default buffer */ }; Here is what the fields contain: - ``PyObject_HEAD`` Standard for every Python object. - ``b_ptr`` Pointer to the memory block that the object uses. - ``b_needsfree`` A flag which is nonzero if the object does owns the memory block, nonzero otherwise. - ``b_base`` If the object does not own the memory block, this is the 'root' object that owns the memory block. Otherwise it is NULL. - ``b_size`` Size of memory block in bytes. - ``b_length`` ... - ``b_index`` If b_base is not NULL, this is the index of this object in the 'root' object. - ``b_objects`` This is a pointer containing a Python object which contains other objects that have to be kept alive as long as this object lives. Either ``None``, or a dictionary. - ``b_value`` A default memory block which can be used by small objects to avoid a PyMem_Malloc calls. The memory block ---------------- Basically, a ctypes object instance has a memory block containing C compatible data, plus the ``b_objects`` Python object pointer. The latter is used to keep referenced objects alive that are referenced by pointers in the memory block. Consider an array of 4 string pointers, defined by this C code:: char *string_array[4]; The ctypes definition is:: >>> from ctypes import * >>> string_array = (c_char_p * 4)() >>> The memory block of ``string_array`` is initialized to all zeros, and retrieving items returns 4 ``None`` objects:: >>> string_array[:] [None, None, None, None] >>> We can assign Python strings to the items, and get them back:: >>> string_array[0] = "foo bar"; string_array[1] = "spam, spam, spam" >>> string_array[0:2] ['foo bar', 'spam, spam, spam'] >>> The memory block contains the *pointers* to the strings (ctypes objects implement the buffer interface, so we can use the following snippet to examine the buffer contents):: >>> print repr(str(buffer(string_array))) # doctest: +SKIP '\x94\xb7\xbd\x00\xfc\x80\xbf\x00\x00\x00\x00\x00\x00\x00\x00\x00' >>> The strings themselves must also be kept in memory, otherwise the pointers in the memory block would access invalid or freed memory. The are stored in a dictionary in the``b_objects`` field of the ``tagCDataObject`` structure defined above. This field is exposed as attribute named ``_objects`` to Python, but you should be aware that this object is only exposed for debugging (and understanding) of ctypes objects, you should *never* modify it:: >>> string_array._objects {'1': 'spam, spam, spam', '0': 'foo bar'} >>> The ``b_objects`` dictionary stores these needed objects as values, at a key that is calculated from the item index or field index. Not all ctypes objects have to keep references, simple types like integers or floats for example can happily live in the memory block, without any other needs. In this case ``b_objects`` contains ``Py_None``, and the dictionary is never created:: >>> int_array = (c_int * 3)() >>> int_array[:] = 1, 2, 3 >>> print int_array._objects None >>> XXX remove this? >>> s_a = (c_char_p * 5210)() >>> s_a[0] = "zero" >>> s_a[255] = "ali baba" >>> s_a[257] = "forty robbers" >>> s_a[1] = "spam and eggs" >>> s_a._objects {'1': 'spam and eggs', '0': 'zero', '101': 'forty robbers', 'ff': 'ali baba'} >>> The important thing to keep in mind is that it must be possible to 'reconstruct' the whole ctypes object from the memory block and the ``b_objects`` pointer. What happens if a ctypes object is stored in another ctypes object field? Define a structure which has a field storing a string array:: >>> class Container(Structure): ... _fields_ = [("count", c_uint), ... ("strings", c_char_p * 4)] ... >>> >>> container = Container() >>> container.strings = string_array >>> container._objects {'1': {'1': 'spam, spam, spam', '0': 'foo bar'}} >>> As we can see, the ``string_array`` ``b_objects`` dictionary has been inserted into the ``container`` ``b_objects`` dictionary at index 1, because 1 is the index of the ``strings`` field. The contents of the ``string_array`` memory block has been copied into the ``container`` memory block as well. Again, things get slighlty more complicated when we use a structure containing a pointer field instead of an array field. In this case, the memory block of the pointer object must be kept alive in addition to the pointer ``b_object`` dictionary. Here is what ctypes does:: >>> class PointerContainer(Structure): ... _fields_ = [("count", c_uint), ... ("string_p", POINTER(c_char_p))] ... >>> pc = PointerContainer() >>> pc.string_p = string_array >>> pc._objects {'1': ({'1': 'spam, spam, spam', '0': 'foo bar'}, <c_char_p_Array_4 object at 0x...>)} >>> So, assigning an array instance to a pointer type field stores a tuple containing the arrays ``b_objects`` dictionary plus the array object itself. Of course, in this case the memory block of ``string_array`` is NOT copied into the ``PointerContainer`` memory block, only the address is copied. What happens if we retrieve the string pointer from the PointerContainer instance? ctypes doesn't do OOR (original object return), ctypes returns a new object on each attribute access:: >>> pc.string_p is pc.string_p False >>> >>> print pc.string_p._objects None >>> print pc.string_p._b_base_ <PointerContainer object at 0x...> >>> >>> other = PointerContainer() >>> other.string_p = pc.string_p >>> print other._objects {'1': {'1': ({'1': 'spam, spam, spam', '0': 'foo bar'}, <c_char_p_Array_4 object at 0x...>)}} >>> >>> x = Container() >>> x.strings = (c_char_p * 4)() >>> print x._objects {'1': {}} >>> x.strings[2] = "python ctypes" >>> print x._objects {'1': {}, '2:1': 'python ctypes'} >>> >>> class X(Structure): ... _fields_ = [("a", c_int), ... ("b", c_int), ... ("c", c_int), ... ("d", c_int), ... ("container", Container)] ... >>> x = X() >>> x.container.strings = (c_char_p * 4)() >>> x.container.strings[1] = "foobar.org" >>> x._objects {'1:4': {}, '1:1:4': 'foobar.org'} >>> |
From: Thomas H. <th...@us...> - 2006-05-19 19:22:40
|
Update of /cvsroot/ctypes/ctypes In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv22317 Modified Files: ChangeLog Log Message: Index: ChangeLog =================================================================== RCS file: /cvsroot/ctypes/ctypes/ChangeLog,v retrieving revision 1.129 retrieving revision 1.130 diff -C2 -d -r1.129 -r1.130 *** ChangeLog 19 May 2006 15:40:28 -0000 1.129 --- ChangeLog 19 May 2006 19:22:37 -0000 1.130 *************** *** 1,2 **** --- 1,14 ---- + 2006-05-19 Thomas Heller <th...@py...> + + * docs\manual\tutorial.txt: Document variable-sized data types. + + * source\_ctypes.c: Allow zero-sized arrays again, although + accessing elements will always raise IndexError. + + * source\_ctypes.c: Change the way unique_key calculates the keys + into the b_objects array. The previous way was broken for arrays + or structures having more than 256 components, which led to + strange errors. + 2006-05-18 Thomas Heller <th...@py...> |
From: Thomas H. <th...@us...> - 2006-05-19 19:22:06
|
Update of /cvsroot/ctypes/ctypes/docs/manual In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv21982 Modified Files: test-tutorial.py Log Message: Add doctest flag OSX. Index: test-tutorial.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/docs/manual/test-tutorial.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** test-tutorial.py 28 Apr 2006 11:40:49 -0000 1.6 --- test-tutorial.py 19 May 2006 19:21:59 -0000 1.7 *************** *** 6,9 **** --- 6,10 ---- WINDOWS = doctest.register_optionflag("WINDOWS") LINUX = doctest.register_optionflag("LINUX") + OSX = doctest.register_optionflag("OSX") SKIP = doctest.register_optionflag("SKIP") *************** *** 21,24 **** --- 22,27 ---- elif LINUX in ex.options and not sys.platform.startswith("linux"): examples.remove(ex) + elif OSX in ex.options and not sys.platform.startswith("darwin"): + examples.remove(ex) elif SKIP in ex.options: examples.remove(ex) |
From: Thomas H. <th...@us...> - 2006-05-19 19:21:34
|
Update of /cvsroot/ctypes/ctypes In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv21951 Modified Files: BUGS Log Message: Remove a bug that was fixed some time ago, and add a new one. Index: BUGS =================================================================== RCS file: /cvsroot/ctypes/ctypes/BUGS,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** BUGS 9 Mar 2006 13:49:53 -0000 1.1 --- BUGS 19 May 2006 19:21:32 -0000 1.2 *************** *** 1,2 **** ! - On platforms that require strict alignment (like sparc solaris), accessing ! unaligned structure fields will crash Python with a core dump. \ No newline at end of file --- 1,2 ---- ! - Memory leak in the _pointer_type_cache dictionary since types are ! made immortal. |
From: Thomas H. <th...@us...> - 2006-05-19 19:21:06
|
Update of /cvsroot/ctypes/ctypes/source In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv21631 Modified Files: _ctypes.c Log Message: Fixed a silly bug in unique_key. Index: _ctypes.c =================================================================== RCS file: /cvsroot/ctypes/ctypes/source/_ctypes.c,v retrieving revision 1.328 retrieving revision 1.329 diff -C2 -d -r1.328 -r1.329 *** _ctypes.c 19 May 2006 15:51:02 -0000 1.328 --- _ctypes.c 19 May 2006 19:21:01 -0000 1.329 *************** *** 1830,1834 **** return NULL; } ! cp += sprintf(cp, ":%x", index); target = target->b_base; } --- 1830,1834 ---- return NULL; } ! cp += sprintf(cp, ":%x", target->b_index); target = target->b_base; } |
From: Thomas H. <th...@us...> - 2006-05-19 18:30:44
|
Update of /cvsroot/ctypes/ctypes/docs/manual In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv4737 Modified Files: tutorial.txt Log Message: Documentation for variable-sized data types. Add todo-item about ctypes.util.find_library. Index: tutorial.txt =================================================================== RCS file: /cvsroot/ctypes/ctypes/docs/manual/tutorial.txt,v retrieving revision 1.27 retrieving revision 1.28 diff -C2 -d -r1.27 -r1.28 *** tutorial.txt 15 May 2006 07:04:40 -0000 1.27 --- tutorial.txt 19 May 2006 18:30:31 -0000 1.28 *************** *** 60,63 **** --- 60,69 ---- XXX Add section for Mac OS X. + Finding shared libraries + ------------------------ + + XXX Add description of ctypes.util.find_library (once I really + understand it enough to describe it). + Accessing functions from loaded dlls ------------------------------------ *************** *** 1123,1131 **** Accessing the contents again constructs a new Python each time! ! Variable size data types ! ------------------------ - XXX describe var-sized arrays - XXX describe resize Bugs, ToDo and non-implemented things --- 1129,1202 ---- Accessing the contents again constructs a new Python each time! ! Variable-sized data types ! ------------------------- ! ! ``ctypes`` provides some support for variable-sized arrays and ! structures (this was added in version 0.9.9.7). ! ! The ``resize`` function can be used to resize the memory buffer of an ! existing ctypes object. The function takes the object as first ! argument, and the requested size in bytes as the second argument. The ! memory block cannot be made smaller than the natural memory block ! specified by the objects type, a ``ValueError`` is raised if this is ! tried:: ! ! >>> short_array = (c_short * 4)() ! >>> print sizeof(short_array) ! 8 ! >>> resize(short_array, 4) ! Traceback (most recent call last): ! ... ! ValueError: minimum size is 8 ! >>> resize(short_array, 32) ! >>> sizeof(short_array) ! 32 ! >>> sizeof(type(short_array)) ! 8 ! >>> ! ! This is nice and fine, but how would one access the additional ! elements contained in this array? Since the type still only knows ! about 4 elements, we get errors accessing other elements:: ! ! >>> short_array[:] ! [0, 0, 0, 0] ! >>> short_array[7] ! Traceback (most recent call last): ! ... ! IndexError: invalid index ! >>> ! ! The solution is to use 1-element arrays; as a special case ctypes does ! no bounds checking on them:: ! ! >>> short_array = (c_short * 1)() ! >>> print sizeof(short_array) ! 2 ! >>> resize(short_array, 32) ! >>> sizeof(short_array) ! 32 ! >>> sizeof(type(short_array)) ! 2 ! >>> short_array[0:8] ! [0, 0, 0, 0, 0, 0, 0, 0] ! >>> short_array[7] = 42 ! >>> short_array[0:8] ! [0, 0, 0, 0, 0, 0, 0, 42] ! >>> ! ! Using 1-element arrays as variable sized fields in structures works as ! well, but they should be used as the last field in the structure ! definition. This example shows a definition from the Windows header ! files:: ! ! class SP_DEVICE_INTERFACE_DETAIL_DATA(Structure): ! _fields_ = [("cbSize", c_int), ! ("DevicePath", c_char * 1)] ! ! Another way to use variable-sized data types with ``ctypes`` is to use ! the dynamic nature of Python, and (re-)define the data type after the ! required size is already known, on a case by case basis. Bugs, ToDo and non-implemented things |