ctypes-commit Mailing List for ctypes (Page 78)
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...> - 2005-01-18 11:06:36
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2265 Modified Files: codegenerator.py Log Message: Include variables into the stats. Index: codegenerator.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/codegenerator.py,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** codegenerator.py 18 Jan 2005 10:54:03 -0000 1.23 --- codegenerator.py 18 Jan 2005 11:06:11 -0000 1.24 *************** *** 300,306 **** --- 300,308 ---- self.done.add(tp) + _variables = 0 def Variable(self, tp): if tp in self.done: return + self._variables += 1 self.done.add(tp) if tp.init is None: *************** *** 518,521 **** --- 520,524 ---- print >> stream, "# Symbols defined:" print >> stream, "#" + print >> stream, "# Variables: %5d" % self._variables print >> stream, "# Struct/Unions: %5d" % self._structures print >> stream, "# Functions: %5d" % self._functiontypes |
From: Thomas H. <th...@us...> - 2005-01-18 10:54:31
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31295 Modified Files: codegenerator.py Log Message: New way to calculate the init value for Variables. The ability to specify a tuple of types for which to generate code. Index: codegenerator.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/codegenerator.py,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** codegenerator.py 17 Jan 2005 14:09:38 -0000 1.22 --- codegenerator.py 18 Jan 2005 10:54:03 -0000 1.23 *************** *** 143,165 **** return t.name ! def init_value(t, init): ! if isinstance(t, typedesc.CvQualifiedType): ! return init_value(t.typ, init) ! if isinstance(t, typedesc.FundamentalType): ! name = ctypes_names[t.name] ! if name in ("c_double", "c_float"): ! return float(init) ! if "unsigned" in t.name: ! return int(init, 16) ! return int(init) ! if isinstance(t, typedesc.PointerType): ! # XXXXXXXXXXXXXXXXX ! return "pointer(%s)" % init_value(t.typ, init) ! raise "HALT" ! # Is this needed? ! ##renames = { ! ## "POINTER(const(WCHAR))": "c_wchar_p", ! ## } def get_real_type(tp): --- 143,198 ---- return t.name ! def decode_value(init): ! # decode init value from gccxml ! if init[0] == "0": ! return int(init, 16) # hex integer ! elif init[0] == "'": ! return eval(init) # character ! elif init[0] == '"': ! return eval(init) # string ! return int(init) # integer ! def init_value(t, init): ! tn = type_name(t) ! if tn in ["c_ulonglong", "c_ulong", "c_uint", "c_ushort", "c_ubyte"]: ! return decode_value(init) ! elif tn in ["c_longlong", "c_long", "c_int", "c_short", "c_byte"]: ! return decode_value(init) ! elif tn in ["c_float", "c_double"]: ! return float(init) ! elif tn == "POINTER(c_char)": ! if init[0] == '"': ! value = eval(init) ! else: ! value = int(init, 16) ! return value ! elif tn == "POINTER(c_wchar)": ! if init[0] == '"': ! value = eval(init) ! else: ! value = int(init, 16) ! if isinstance(value, str): ! value = value[:-1] # gccxml outputs "D\000S\000\000" for L"DS" ! value = value.decode("utf-16") # XXX Is this correct? ! return value ! elif tn == "c_void_p": ! if init[0] == "0": ! value = int(init, 16) ! else: ! value = int(init) # hm.. ! # Hm, ctypes represents them as SIGNED int ! return value ! elif tn == "c_char": ! return decode_value(init) ! elif tn == "c_wchar": ! value = decode_value(init) ! if isinstance(value, int): ! return unichr(value) ! return value ! elif tn.startswith("POINTER("): ! # Hm, POINTER(HBITMAP__) for example ! return decode_value(init) ! else: ! raise ValueError, "cannot decode %s(%r)" % (tn, init) def get_real_type(tp): *************** *** 274,279 **** # wtypes.h contains IID_IProcessInitControl, for example return print >> self.stream, \ ! "%s = %s" % (tp.name, init_value(tp.typ, tp.init)) def EnumValue(self, tp): --- 307,319 ---- # wtypes.h contains IID_IProcessInitControl, for example return + try: + v = init_value(tp.typ, tp.init) + except (TypeError, ValueError), detail: + print "Could not init", detail + return print >> self.stream, \ ! "%s = %r # %s" % (tp.name, ! init_value(tp.typ, tp.init), ! type_name(tp.typ)) def EnumValue(self, tp): *************** *** 498,502 **** use_decorators=False, known_symbols=None, ! searched_dlls=None): # expressions is a sequence of compiled regular expressions, # symbols is a sequence of names --- 538,543 ---- use_decorators=False, known_symbols=None, ! searched_dlls=None, ! types=None): # expressions is a sequence of compiled regular expressions, # symbols is a sequence of names *************** *** 506,509 **** --- 547,553 ---- todo = [] + if types: + items = [i for i in items if isinstance(i, types)] + if symbols: syms = set(symbols) |
From: Thomas H. <th...@us...> - 2005-01-17 20:27:41
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3798 Modified Files: cparser_config.py Log Message: ome changes for linux. Index: cparser_config.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/cparser_config.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** cparser_config.py 17 Jan 2005 15:58:03 -0000 1.1 --- cparser_config.py 17 Jan 2005 20:27:26 -0000 1.2 *************** *** 2,6 **** # # XXX should be made platform specific! ! import re # C keywords, according to MSDN, plus some additional --- 2,6 ---- # # XXX should be made platform specific! ! import re, sys, os # C keywords, according to MSDN, plus some additional *************** *** 27,31 **** # defines we know that won't work # for windows.h ! EXCLUDED = """ NOTIFYICONDATAA_V1_SIZE NOTIFYICONDATAA_V2_SIZE --- 27,31 ---- # defines we know that won't work # for windows.h ! EXCLUDED_win32 = """ NOTIFYICONDATAA_V1_SIZE NOTIFYICONDATAA_V2_SIZE *************** *** 64,74 **** """.strip().split() EXCLUDED = [text for text in EXCLUDED if not text.startswith("#")] ! EXCLUDED_RE = r""" ^DECLSPEC\w*$ """.strip().split() EXCLUDED_RE = [re.compile(pat) for pat in EXCLUDED_RE if not pat.startswith("#")] --- 64,93 ---- """.strip().split() + EXCLUDED_linux = """ + _IOT_termios + """.strip().split() + + if sys.platform == "win32": + EXCLUDED = EXCLUDED_win32 + elif sys.platform.startswith("linux"): + EXCLUDED = EXCLUDED_linux + EXCLUDED = [text for text in EXCLUDED if not text.startswith("#")] ! EXCLUDED_RE_win32 = r""" ^DECLSPEC\w*$ """.strip().split() + EXCLUDED_RE_linux = r""" + ^__\w*$ + ^__attribute_\w*_$ + """.strip().split() + + if sys.platform == "win32": + EXCLUDED_RE = EXCLUDED_RE_win32 + elif sys.platform.startswith("linux"): + EXCLUDED_RE = EXCLUDED_RE_linux + EXCLUDED_RE = [re.compile(pat) for pat in EXCLUDED_RE if not pat.startswith("#")] |
From: Thomas H. <th...@us...> - 2005-01-17 19:30:48
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24431 Modified Files: cparser.py Log Message: Using subprocess is not so simple as it should ;-(. Index: cparser.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/cparser.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** cparser.py 17 Jan 2005 15:58:03 -0000 1.1 --- cparser.py 17 Jan 2005 19:30:31 -0000 1.2 *************** *** 2,6 **** from cparser_config import C_KEYWORDS, EXCLUDED, EXCLUDED_RE import gccxmlparser, typedesc - import subprocess if sys.platform == "win32": --- 2,5 ---- *************** *** 42,51 **** fname = self.create_source_file(lines) try: ! args = ["gccxml", "--preprocess", "-dM", self.options.flags, fname] ! proc = subprocess.Popen(args, stdout=subprocess.PIPE) ! data, errors = proc.communicate() ! retcode = proc.wait() ! if retcode: ! raise CompilerError, "gccxml returned %s" % retcode finally: os.remove(fname) --- 41,50 ---- fname = self.create_source_file(lines) try: ! args = ["gccxml", "--preprocess", "-dM", fname] ! if self.options.flags: ! args.append(self.options.flags) ! i, o = os.popen4(" ".join(args)) ! i.close() ! data = o.read() finally: os.remove(fname) *************** *** 58,63 **** xmlfile, and remove the source file again.""" fname = self.create_source_file(lines) try: ! retcode = subprocess.call(["gccxml", self.options.flags, fname, "-fxml=%s" % xmlfile]) if retcode: raise CompilerError, "gccxml returned %s" % retcode --- 57,65 ---- xmlfile, and remove the source file again.""" fname = self.create_source_file(lines) + args = ["gccxml", fname, "-fxml=%s" % xmlfile] + if self.options.flags: + args.append(self.options.flags) try: ! retcode = os.system(" ".join(args)) if retcode: raise CompilerError, "gccxml returned %s" % retcode |
From: Thomas H. <th...@us...> - 2005-01-17 15:58:20
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16194 Modified Files: h2xml.py Added Files: cparser_config.py cparser.py Log Message: New and improved h2xml.py script. Uses cparser.py, which can even find and resolve preprocessor symbols in header files. cparser_config.py should be platform dependend. --- NEW FILE: cparser.py --- import sys, os, re, tempfile from cparser_config import C_KEYWORDS, EXCLUDED, EXCLUDED_RE import gccxmlparser, typedesc import subprocess if sys.platform == "win32": def _locate_gccxml(): import _winreg for subkey in (r"Software\gccxml", r"Software\Kitware\GCC_XML"): for root in (_winreg.HKEY_CURRENT_USER, _winreg.HKEY_LOCAL_MACHINE): try: hkey = _winreg.OpenKey(root, subkey, 0, _winreg.KEY_READ) except WindowsError, detail: if detail.errno != 2: raise else: return _winreg.QueryValueEx(hkey, "loc")[0] + r"\bin" loc = _locate_gccxml() if loc: os.environ["PATH"] = loc class CompilerError(Exception): pass class IncludeParser(object): def create_source_file(self, lines, ext=".cpp"): "Create a temporary file, write lines to it, and return the filename" fd, fname = tempfile.mkstemp(ext, text=True) stream = os.fdopen(fd, "w") if lines: for line in lines: stream.write("%s\n" % line) stream.close() return fname def compile_and_dump(self, lines=None): """Create a temporary source file, dump preprocessor definitions, and remove the source file again.""" fname = self.create_source_file(lines) try: args = ["gccxml", "--preprocess", "-dM", self.options.flags, fname] proc = subprocess.Popen(args, stdout=subprocess.PIPE) data, errors = proc.communicate() retcode = proc.wait() if retcode: raise CompilerError, "gccxml returned %s" % retcode finally: os.remove(fname) return [line[len("#define "):] for line in data.splitlines() if line.startswith("#define ")] def create_xml(self, lines, xmlfile): """Create a temporary source file, 'compile' with gccxml to an xmlfile, and remove the source file again.""" fname = self.create_source_file(lines) try: retcode = subprocess.call(["gccxml", self.options.flags, fname, "-fxml=%s" % xmlfile]) if retcode: raise CompilerError, "gccxml returned %s" % retcode finally: os.remove(fname) def get_defines(self, include_file): """'Compile' an include file with gccxml, and return a dictionary of preprocessor definitions. Empty and compiler internal definitions are not included.""" # compiler internal definitions lines = self.compile_and_dump() predefined = [line.split(None, 1)[0] for line in lines] # all definitions lines = self.compile_and_dump(['#include "%s"' % include_file]) defined = [line.split(None, 1) for line in lines] # remove empty and compiler internal definitions defined = [pair for pair in defined if len(pair) == 2 and pair[0] not in predefined] return dict(defined) wordpat = re.compile("^[a-zA-Z_][a-zA-Z0-9_]*$") def is_excluded(self, name, value): INVALID_CHARS = "=/{}&;" if "(" in name: return "macro with parameters" if value in C_KEYWORDS: return "value is keyword" if name in EXCLUDED: return "excluded" for pat in EXCLUDED_RE: if pat.match(name): return "excluded (regex)" if value[0] in INVALID_CHARS or value[-1] in INVALID_CHARS: return "cannot be a value" if self.wordpat.match(name) and self.wordpat.match(value): # aliases are handled later, when (and if!) the rhs is known return "IS_ALIAS" return False def filter_definitions(self, defines): "Return a dict of aliases, and another dict of constants and literals" result = {} aliases = {} for name, value in defines.iteritems(): why = self.is_excluded(name, value) if why == "IS_ALIAS": aliases[name] = value if not why: result[name] = value return aliases, result ################################################################ def find_types(self, include_file, defines): source = [] source.append('#include "%s"' % include_file) source.append("#define DECLARE(sym) template <typename T> T symbol_##sym(T) {}") source.append("#define DEFINE(sym) symbol_##sym(sym)") for name in defines: # create a function template for each value source.append("DECLARE(%s)" % name) source.append("int main() {") for name in defines: # instantiate a function template. # The return type of the function is the symbol's type. source.append(" DEFINE(%s);" % name) source.append("}") fd, fname = tempfile.mkstemp(".xml") os.close(fd) self.create_xml(source, fname) try: items = gccxmlparser.parse(fname) finally: # make sure the temporary file is removed after using it os.remove(fname) types = {} for i in items: name = getattr(i, "name", None) if name and name.startswith("symbol_"): name = name[len("symbol_"):] typ = i.returns try: typ = self.c_type_name(i.returns) except TypeError, detail: # XXX Warning? print >> sys.stderr, "skipped #define %s %s" % (name, defines[name]), detail else: types[name] = typ return types def create_final_xml(self, include_file, types): source = [] source.append('#include "%s"' % include_file) for name, value in types.iteritems(): source.append("const %s cpp_sym_%s = %s;" % (types[name], name, name)) fname = self.options.xmlfile self.create_xml(source, fname) def c_type_name(self, tp): "Return the C type name for this type." if isinstance(tp, typedesc.FundamentalType): return tp.name elif isinstance(tp, typedesc.PointerType): return "%s *" % self.c_type_name(tp.typ) elif isinstance(tp, typedesc.CvQualifiedType): return self.c_type_name(tp.typ) elif isinstance(tp, typedesc.Typedef): return self.c_type_name(tp.typ) elif isinstance(tp, typedesc.Structure): return tp.name raise TypeError, type(tp).__name__ ################################################################ def parse(self, include_file, options): """Main method. The options object must have these attribuites: verbose - integer flags - string """ self.options = options if options.verbose: print >> sys.stderr, "finding definitions ..." defines = self.get_defines(include_file) if options.verbose: print >> sys.stderr, "%d found" % len(defines) print >> sys.stderr, "filtering definitions ..." aliases, defines = self.filter_definitions(defines) if options.verbose: print >> sys.stderr, "%d values, %d aliases" % (len(defines), len(aliases)) if options.verbose: print >> sys.stderr, "finding definitions types ..." # invoke C++ template magic types = self.find_types(include_file, defines) if options.verbose: print >> sys.stderr, "found %d types ..." % len(types) if options.verbose: print >> sys.stderr, "creating xml output file ..." self.create_final_xml(include_file, types) # Should we now insert the aliases into the xml, again? ##if __name__ == "__main__": ## class options(object): ## pass ## options = options() ## options.verbose = 1 ## options.flags = "-D WIN32_LEAN_AND_MEAN -D NO_STRICT" ## p = IncludeParser() ## options.xmlfile = "windows.xml" ## p.parse("windows.h", options) Index: h2xml.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/h2xml.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** h2xml.py 10 Jan 2005 16:24:29 -0000 1.5 --- h2xml.py 17 Jan 2005 15:58:03 -0000 1.6 *************** *** 1,4 **** --- 1,6 ---- """h2xml - convert C include file(s) into an xml file by running gccxml.""" import sys, os, tempfile + import cparser + from optparse import OptionParser if sys.platform == "win32": *************** *** 22,75 **** ################################################################ - class CompilerError(Exception): - pass - - # Create a C file containing #includes to the specified filenames. - # Run GCCXML to create an XML file, and return the xml filename. - def run_gccxml(fnames, options, verbose=0, xml_file=None): - # fnames is the sequence of include files - # options is seuqence of strings containing command line options for GCCXML - # verbose - integer specifying the verbosity - # - # returns the filename of the generated XML file - - # write a temporary C file - handle, c_file = tempfile.mkstemp(suffix=".c", text=True) - if verbose: - print >> sys.stderr, "writing temporary C source file %s" % c_file - ## os.write(handle, 'extern "C" {\n'); - for fname in fnames: - os.write(handle, '#include <%s>\n' % fname) - ## os.write(handle, '}'); - os.close(handle) - - if xml_file is None: - handle, xml_file = tempfile.mkstemp(suffix=".xml", text=True) - os.close(handle) - - if options: - options = " ".join(options) - else: - options = "" - - try: - if verbose: - print >> sys.stderr, r"gccxml %s %s -fxml=%s" % (options, c_file, xml_file) - i, o = os.popen4(r"gccxml %s %s -fxml=%s" % (options, c_file, xml_file)) - i.close() - sys.stderr.write(o.read()) - retval = o.close() - if retval: - raise CompilerError, "gccxml returned error %s" % retval - return xml_file - finally: - if verbose: - print >> sys.stderr, "Deleting temporary file %s" % c_file - os.remove(c_file) - - ################################################################ - def main(): - from optparse import OptionParser def add_option(option, opt, value, parser): --- 24,28 ---- *************** *** 78,83 **** parser = OptionParser() ## parser.add_option("-h", action="help") ! parser.add_option("-v", "--verbose", ! dest="verbose", action="store_true", default=False) --- 31,36 ---- parser = OptionParser() ## parser.add_option("-h", action="help") ! parser.add_option("-q", "--quite", ! dest="quiet", action="store_true", default=False) *************** *** 89,93 **** dest="gccxml_options", help="macros to define", ! metavar="defines", default=[]) parser.add_option("-U", --- 42,46 ---- dest="gccxml_options", help="macros to define", ! metavar="NAME[=VALUE]", default=[]) parser.add_option("-U", *************** *** 96,100 **** callback=add_option, help="macros to undefine", ! metavar="defines") parser.add_option("-I", --- 49,53 ---- callback=add_option, help="macros to undefine", ! metavar="NAME") parser.add_option("-I", *************** *** 103,111 **** callback=add_option, dest="gccxml_options", ! help="include directories", ! metavar="defines") parser.add_option("-o", ! dest="xml_file", help="XML output filename", default=None) --- 56,64 ---- callback=add_option, dest="gccxml_options", ! help="additional include directories", ! metavar="DIRECTORY") parser.add_option("-o", ! dest="xmlfile", help="XML output filename", default=None) *************** *** 117,130 **** return 1 try: ! xmlfile = run_gccxml(files, options.gccxml_options, options.verbose, options.xml_file) ! except CompilerError, detail: sys.exit(1) - if options.xml_file is None: - if options.verbose: - print >> sys.stderr, "Deleting temporary file %s" % xmlfile - os.remove(xmlfile) - if __name__ == "__main__": main() --- 70,86 ---- return 1 + options.flags = " ".join(options.gccxml_options) + + options.verbose = not options.quiet + try: ! parser = cparser.IncludeParser() ! parser.parse(files[0], options) ! except cparser.CompilerError, detail: ! import traceback ! traceback.print_exc() ! ## print detail sys.exit(1) if __name__ == "__main__": main() --- NEW FILE: cparser_config.py --- # cparser_config.py - configuration items for cparser.py # # XXX should be made platform specific! import re # C keywords, according to MSDN, plus some additional # names like __forceinline, near, far. # Skip all definitions where the rhs is a keyword # Example: #define CALLBACK __stdcall # # Hm, should types be handled differently? # Example: #define VOID void C_KEYWORDS = """__asm else main struct __assume enum __multiple_inheritance switch auto __except __single_inheritance template __based explicit __virtual_inheritance this bool extern mutable thread break false naked throw case __fastcall namespace true catch __finally new try __cdecl float noreturn __try char for operator typedef class friend private typeid const goto protected typename const_cast if public union continue inline register unsigned __declspec __inline default int return uuid delete __int8 short __uuidof dllexport __int16 signed virtual dllimport __int32 sizeof void do __int64 static volatile double __leave static_cast wmain dynamic_cast long __stdcall while far near __forceinline __w64 __noop""".split() # defines we know that won't work # for windows.h EXCLUDED = """ NOTIFYICONDATAA_V1_SIZE NOTIFYICONDATAA_V2_SIZE PROPSHEETHEADERA_V1_SIZE PROPSHEETHEADERA_V2_SIZE PROPSHEETHEADERW_V2_SIZE NOTIFYICONDATAW_V2_SIZE s_imp s_host s_lh s_net s_addr h_addr s_impno _VARIANT_BOOL MIDL_uhyper WINSCARDDATA __MIDL_DECLSPEC_DLLIMPORT __MIDL_DECLSPEC_DLLEXPORT NCB_POST STDAPI STDAPIV WINAPI SHDOCAPI WINOLEAUTAPI WINOLEAPI APIENTRY EXTERN_C FIRMWARE_PTR STDMETHODIMPV STDMETHODIMP DEFAULT_UNREACHABLE MAXLONGLONG IMAGE_ORDINAL_FLAG64 SECURITY_NT_AUTHORITY """.strip().split() EXCLUDED = [text for text in EXCLUDED if not text.startswith("#")] EXCLUDED_RE = r""" ^DECLSPEC\w*$ """.strip().split() EXCLUDED_RE = [re.compile(pat) for pat in EXCLUDED_RE if not pat.startswith("#")] |
From: Thomas H. <th...@us...> - 2005-01-17 14:10:39
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26519 Modified Files: xml2py.py Log Message: Index: xml2py.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/xml2py.py,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** xml2py.py 10 Jan 2005 16:21:15 -0000 1.8 --- xml2py.py 17 Jan 2005 14:10:15 -0000 1.9 *************** *** 1,4 **** - # bugs: - # packing of structures/unions with bitfields? See '##XXX FIXME' import sys, re from optparse import OptionParser --- 1,2 ---- *************** *** 33,37 **** netapi32 rpcrt4""".split() - ##glut32 ##rpcndr --- 31,34 ---- |
From: Thomas H. <th...@us...> - 2005-01-17 14:09:47
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26314 Modified Files: codegenerator.py Log Message: Ignore uninitialized variable definitions, for now. Index: codegenerator.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/codegenerator.py,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** codegenerator.py 14 Jan 2005 10:48:39 -0000 1.21 --- codegenerator.py 17 Jan 2005 14:09:38 -0000 1.22 *************** *** 271,274 **** --- 271,277 ---- return self.done.add(tp) + if tp.init is None: + # wtypes.h contains IID_IProcessInitControl, for example + return print >> self.stream, \ "%s = %s" % (tp.name, init_value(tp.typ, tp.init)) |
From: Thomas H. <th...@us...> - 2005-01-17 14:08:49
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26153 Removed Files: _makexml.py Log Message: Final version, but obsolete anyway. Will be replaced asap. --- _makexml.py DELETED --- |
From: Thomas H. <th...@us...> - 2005-01-17 14:08:19
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26076 Modified Files: _makexml.py Log Message: Final version, but obsolete anyway. Will be replaced asap. Index: _makexml.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/_makexml.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** _makexml.py 14 Jan 2005 14:44:36 -0000 1.5 --- _makexml.py 17 Jan 2005 14:08:07 -0000 1.6 *************** *** 1,4 **** import os, re ! from gccxmlparser import parse import typedesc --- 1,4 ---- import os, re ! import gccxmlparser import typedesc *************** *** 113,119 **** name, value = items ! reason = is_excluded(name, value) ! if reason: ! log.write("%s: #define %s %s\n" % (reason, name, value)) continue --- 113,119 ---- name, value = items ! why = is_excluded(name, value) ! if why: ! log.write("%s: #define %s %s\n" % (why, name, value)) continue *************** *** 154,160 **** raise TypeError, type(tp).__name__ ! ################################################################ def create_file(): ! ofi = open("glut.cpp", "w") ## ofi.write('#include <gl/glut.h>\n') # ofi.write("#define WIN32_LEAN_AND_MEAN\n") --- 154,160 ---- raise TypeError, type(tp).__name__ ! ################################ def create_file(): ! ofi = open("xxx.cpp", "w") ## ofi.write('#include <gl/glut.h>\n') # ofi.write("#define WIN32_LEAN_AND_MEAN\n") *************** *** 175,187 **** ################################################################ ! # parse a C header file, and dump the preprocessor symbols log = open("skipped.txt", "w") ! create_file() # find the preprocessor defined symbols print "... finding preprocessor symbol names" ! defs = gccxml_get_defines("glut.cpp") print "%d '#define' symbols found" % len(defs) --- 175,192 ---- ################################################################ ! # ! # script section ! # ! ################################################################ ! # find the preprocessor symbols from a C header file log = open("skipped.txt", "w") ! ofi = create_file() ! ofi.close() # find the preprocessor defined symbols print "... finding preprocessor symbol names" ! defs = gccxml_get_defines(ofi.name) print "%d '#define' symbols found" % len(defs) *************** *** 193,217 **** # The function name can later be used to retrieve the symbol name again, # and the function's return type is the symbols's type. ! ofi = create_file() ! MAGIC = """ #define DECLARE(sym) template <typename T> T symbol_##sym(T) {} #define DEFINE(sym) symbol_##sym(sym) """ ! ofi.write(MAGIC) ! for name in defs: ! ofi.write("// #define %s %s\n" % (name, defs[name])) ! ofi.write("DECLARE(%s)\n" % name); ! ofi.write("int main() {\n") ! for name in defs: ! ofi.write(" DEFINE(%s);\n" % name); ! ofi.write("}\n") ! ofi.close() print "... finding preprocessor symbol types" # compile the file ! os.system("gccxml glut.cpp -fxml=glut.xml") ! # parse the result ! items = parse("glut.xml") # create a new C++ file which will later allow to retrieve the name, --- 198,227 ---- # The function name can later be used to retrieve the symbol name again, # and the function's return type is the symbols's type. ! ! CPPMAGIC = """ #define DECLARE(sym) template <typename T> T symbol_##sym(T) {} #define DEFINE(sym) symbol_##sym(sym) """ ! ! def invoke_templates(ofi, defs): ! ofi.write(CPPMAGIC) ! for name in defs: ! ofi.write("// #define %s %s\n" % (name, defs[name])) ! ofi.write("DECLARE(%s)\n" % name); ! ofi.write("int main() {\n") ! for name in defs: ! ofi.write(" DEFINE(%s);\n" % name); ! ofi.write("}\n") ! ofi.close() ! os.system("gccxml %s -fxml=glut.xml" % ofi.name) ! # parse the result ! items = gccxmlparser.parse("glut.xml") ! return items print "... finding preprocessor symbol types" # compile the file ! ofi = create_file() ! items = invoke_templates(ofi, defs) # create a new C++ file which will later allow to retrieve the name, *************** *** 228,238 **** # HWNDNOTOPMOST: ((HWND) -2), HWND is a structure continue ! codelines.append("const %s cpp_sym_%s = %s;" % (symtype, symname, symname)) print "created %d definitions" % len(codelines) ofi = create_file() for c in codelines: ! ofi.write("%s\n" % c) ofi.close() --- 238,250 ---- # HWNDNOTOPMOST: ((HWND) -2), HWND is a structure continue ! codelines.append("const %s cpp_sym_%s = %s;\n" % (symtype, symname, symname)) print "created %d definitions" % len(codelines) ofi = create_file() + ofi.write("namespace cpp_symbols {\n") for c in codelines: ! ofi.write(c) ! ofi.write("}\n") ofi.close() *************** *** 241,246 **** # will be used to generate Python code print "... finding preprocessor symbol values" ! os.system("gccxml glut.cpp -fxml=glut.xml") ! # now we should reinsert the aliases list again --- 253,258 ---- # will be used to generate Python code print "... finding preprocessor symbol values" ! os.system("gccxml %s -fxml=glut.xml" % ofi.name) ! os.remove(ofi.name) # now we should reinsert the aliases list again |
From: Thomas H. <th...@us...> - 2005-01-15 17:16:17
|
Update of /cvsroot/ctypes/ctypes In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29442 Modified Files: ChangeLog Log Message: Record changes. Index: ChangeLog =================================================================== RCS file: /cvsroot/ctypes/ctypes/ChangeLog,v retrieving revision 1.74 retrieving revision 1.75 diff -C2 -d -r1.74 -r1.75 *** ChangeLog 2 Dec 2004 21:04:50 -0000 1.74 --- ChangeLog 15 Jan 2005 17:16:06 -0000 1.75 *************** *** 1,7 **** 2004-12-02 Thomas Heller <th...@py...> ! * Structure types as restype of functions do work now. But I have ! severe doubts that passing structures by values works. Not to ! speak about callback functions! The _fields_ attribute is now handled correctly in Structure --- 1,28 ---- + 2005-01-15 Thomas Heller <th...@py...> + + * source\_ctypes.c: WINFUNCTYPE (and CFUNCTYPE) can now be called + with three parameters: integer, string, class. It returns an + unbound method fpr class, calling into a COM vtable at the integer + index. string is the method name. + + Better error chcking, and fix a compiler warning in CFuncPtr_New. + + 2004-12-30 Thomas Heller <th...@py...> + + * _ctypes.c (_CData_set): Assinging None to a POINTER structure + field makes a NULL pointer. + + * source\_ctypes.c (Pointer_ass_item): Prevent NULL pointer access + when assigning to pointer instances. + + 2004-12-17 Thomas Heller <th...@py...> + + * source/callbacks.c: Corrected the exception handling in callback + functions. SystemExit in a callback now actually exits Python. + 2004-12-02 Thomas Heller <th...@py...> ! * Structure types as restype and in argtypes of functions do work ! now. Not sure about callback functions. The _fields_ attribute is now handled correctly in Structure |
From: Thomas H. <th...@us...> - 2005-01-15 17:13:23
|
Update of /cvsroot/ctypes/ctypes/source In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28853 Modified Files: _ctypes.c Log Message: WINFUNCTYPE (and CFUNCTYPE) can now be called with three parameters: integer, string, class. It returns an unbound method fpr class, calling into a COM vtable at the integer index. string is the method name. Index: _ctypes.c =================================================================== RCS file: /cvsroot/ctypes/ctypes/source/_ctypes.c,v retrieving revision 1.197 retrieving revision 1.198 diff -C2 -d -r1.197 -r1.198 *** _ctypes.c 15 Jan 2005 16:47:14 -0000 1.197 --- _ctypes.c 15 Jan 2005 17:13:14 -0000 1.198 *************** *** 2288,2293 **** int index; char *name = NULL; ! if (!PyArg_ParseTuple(args, "is", &index, &name)) return NULL; --- 2288,2294 ---- int index; char *name = NULL; + PyObject *cls = NULL; ! if (!PyArg_ParseTuple(args, "is|O", &index, &name, &cls)) return NULL; *************** *** 2295,2298 **** --- 2296,2301 ---- self->index = index + 0x1000; + if (cls) + return PyMethod_New(self, NULL, cls); return (PyObject *)self; } *************** *** 2305,2309 **** "i" - function address "sO" - function name, dll object (with an integer handle) ! "is" - vtable index, method name, creates COM method pointers "O" - must be a callable, creates a C callable function */ --- 2308,2313 ---- "i" - function address "sO" - function name, dll object (with an integer handle) ! "is" - vtable index, method name, creates callable calling COM vtbl ! "isO" - vtable index, method name, class, creates unbound method calling COM vtbl "O" - must be a callable, creates a C callable function */ *************** *** 2320,2324 **** } ! if (2 == PyTuple_GET_SIZE(args)) { #ifdef MS_WIN32 if (PyInt_Check(PyTuple_GET_ITEM(args, 0))) --- 2324,2328 ---- } ! if (2 <= PyTuple_GET_SIZE(args)) { #ifdef MS_WIN32 if (PyInt_Check(PyTuple_GET_ITEM(args, 0))) |
From: Thomas H. <th...@us...> - 2005-01-15 16:47:24
|
Update of /cvsroot/ctypes/ctypes/source In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23539 Modified Files: _ctypes.c Log Message: Avoid a compiler warning. Better error checking in CFuncPtr_new. Index: _ctypes.c =================================================================== RCS file: /cvsroot/ctypes/ctypes/source/_ctypes.c,v retrieving revision 1.196 retrieving revision 1.197 diff -C2 -d -r1.196 -r1.197 *** _ctypes.c 15 Jan 2005 10:20:04 -0000 1.196 --- _ctypes.c 15 Jan 2005 16:47:14 -0000 1.197 *************** *** 2328,2336 **** } ! if (1 == PyTuple_GET_SIZE(args) && PyInt_Check(PyTuple_GET_ITEM(args, 0))) { CDataObject *ob; ob = (CDataObject *)GenericCData_new(type, args, kwds); ! /* XXX The following correctly gives a warning */ ! *(void **)ob->b_ptr = PyInt_AsLong(PyTuple_GET_ITEM(args, 0)); return (PyObject *)ob; } --- 2328,2340 ---- } ! if (1 == PyTuple_GET_SIZE(args) ! && PyInt_Check(PyTuple_GET_ITEM(args, 0)) ! || PyLong_Check(PyTuple_GET_ITEM(args, 0))) { CDataObject *ob; + void *ptr = PyLong_AsVoidPtr(PyTuple_GET_ITEM(args, 0)); + if (ptr == NULL) + return NULL; ob = (CDataObject *)GenericCData_new(type, args, kwds); ! *(void **)ob->b_ptr = ptr; return (PyObject *)ob; } *************** *** 2344,2357 **** } if (kwds && PyDict_GetItemString(kwds, "options")) { ! /* XXX XXX This gives the possibility to pass additional ! options. For COM method *implementations*, we would ! probably want different behaviour than in 'normal' callback ! functions: return a HRESULT if an exception occurrs in the ! callback, and print the traceback not only on the console, ! but also to OutputDebugString() or something like that. ! */ ! /* nothing so far ;-) */; } dict = PyType_stgdict((PyObject *)type); --- 2348,2363 ---- } + /* XXX XXX This would allow to pass additional options. For COM + method *implementations*, we would probably want different + behaviour than in 'normal' callback functions: return a HRESULT if + an exception occurrs in the callback, and print the traceback not + only on the console, but also to OutputDebugString() or something + like that. + */ + /* if (kwds && PyDict_GetItemString(kwds, "options")) { ! ... } + */ dict = PyType_stgdict((PyObject *)type); *************** *** 2365,2380 **** /*****************************************************************/ - /* - Thoughts: - - 1. The thunk should keep (and later free) references to callable and - argtypes itself. - - 2. The thunk should probably be wrapped up in a PyCObject, and then - stored in the _objects list. - - 3. We absolutely need GC support. - - */ /* The thunk keeps unowned references to callable and dict->argtypes so we have to keep them alive somewhere else: callable is kept in self, --- 2371,2374 ---- |
From: Thomas H. <th...@us...> - 2005-01-15 10:20:14
|
Update of /cvsroot/ctypes/ctypes/source In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18945 Modified Files: _ctypes.c Log Message: Better error message for COM method calls, when the 'this' parameter is missing or wrong. Index: _ctypes.c =================================================================== RCS file: /cvsroot/ctypes/ctypes/source/_ctypes.c,v retrieving revision 1.195 retrieving revision 1.196 diff -C2 -d -r1.195 -r1.196 *** _ctypes.c 30 Dec 2004 13:36:25 -0000 1.195 --- _ctypes.c 15 Jan 2005 10:20:04 -0000 1.196 *************** *** 2431,2439 **** /* It's a COM method */ CDataObject *this; ! this = (CDataObject *)PyTuple_GetItem(args, 0); ! if (!this || !CDataObject_Check(this)) { ! /* XXX Better error msg when this == NULL */ PyErr_SetString(PyExc_TypeError, ! "wrong type for this arg"); return NULL; } --- 2431,2443 ---- /* It's a COM method */ CDataObject *this; ! this = (CDataObject *)PyTuple_GetItem(args, 0); /* borrowed ref! */ ! if (!this) { ! PyErr_SetString(PyExc_ValueError, ! "native com method call without 'this' parameter"); ! return NULL; ! } ! if (!CDataObject_Check(this)) { PyErr_SetString(PyExc_TypeError, ! "Expected a COM this pointer as first argument"); return NULL; } *************** *** 3218,3221 **** --- 3222,3226 ---- proto = stgdict->proto; + /* XXXXXX MAKE SURE PROTO IS NOT NULL! */ itemdict = PyType_stgdict(proto); size = itemdict->size; *************** *** 3257,3260 **** --- 3262,3266 ---- size = stgdict->size / stgdict->length; + /* XXXXX Make sure proto is NOT NULL! */ return CData_set((PyObject *)self, stgdict->proto, stgdict->setfunc, value, index, size, *(void **)self->b_ptr); |
From: Thomas H. <th...@us...> - 2005-01-14 14:44:49
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19212 Modified Files: _makexml.py Log Message: Lots of code not needed anymore. Index: _makexml.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/_makexml.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** _makexml.py 14 Jan 2005 14:28:00 -0000 1.4 --- _makexml.py 14 Jan 2005 14:44:36 -0000 1.5 *************** *** 79,84 **** INVALID_CHARS = "=/{};&" - log = open("skipped.txt", "w") - def is_excluded(name, value): if "(" in name: --- 79,82 ---- *************** *** 164,177 **** return ofi - ################################################################ - # parse a C header file, and dump the preprocessor symbols - create_file() - - # find the preprocessor defined symbols - print "... finding preprocessor symbol names" - defs = gccxml_get_defines("glut.cpp") - - print "%d '#define' symbols found" % len(defs) - def find_aliases(defs): aliases = {} --- 162,165 ---- *************** *** 186,232 **** return aliases - aliases = find_aliases(defs) - - print "%d symbols are name aliases" % len(aliases) - ################################################################ ! # parse the standard output ! print "... processing with gccxml" ! os.system("gccxml glut.cpp -fxml=glut.xml") ! ! print "... parsing gccxml output:", ! items = parse("glut.xml") ! print "%d type descriptions found" % len(items) ! ! types = {} ! for i in items: ! name = getattr(i, "name", None) ! if name: ! types[name] = i ! ##interesting = (typedesc.Function,) ! ##interesting = (typedesc.EnumValue,) ! interesting = (typedesc.FundamentalType, typedesc.Function, typedesc.FunctionType, ! typedesc.Typedef) ! # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX here continue to work... ! # filter the symbols ... ! newdefs = {} ! skipped = 0 ! known = set() ! for name, value in defs.iteritems(): ! if value in types: ! # Ah, we know the *type* and the *value* of this item already ! skipped += 1 ! ## print "SKIPPED", type(types[value]).__name__, name, value ! known.add(name) ! pass ! else: ! newdefs[name] = value ! print "skipped %d symbols, type and value are known from XML" % skipped ! print "Remaining %s items" % len(newdefs) ! defs = newdefs ################################################################ --- 174,191 ---- return aliases ################################################################ ! # parse a C header file, and dump the preprocessor symbols ! log = open("skipped.txt", "w") ! create_file() ! # find the preprocessor defined symbols ! print "... finding preprocessor symbol names" ! defs = gccxml_get_defines("glut.cpp") ! print "%d '#define' symbols found" % len(defs) ! aliases = find_aliases(defs) ! print "%d symbols are name aliases" % len(aliases) ################################################################ *************** *** 253,257 **** # compile the file os.system("gccxml glut.cpp -fxml=glut.xml") - # parse the result items = parse("glut.xml") --- 212,215 ---- *************** *** 285,287 **** --- 243,247 ---- os.system("gccxml glut.cpp -fxml=glut.xml") + # now we should reinsert the aliases list again + print "took %.2f seconds" % (time.clock() - start) |
From: Thomas H. <th...@us...> - 2005-01-14 14:28:09
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14497 Modified Files: _makexml.py Log Message: A slightly simpler C++ template speeds the script up from 62 sec to 27 sec (!). Index: _makexml.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/_makexml.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** _makexml.py 14 Jan 2005 14:15:01 -0000 1.3 --- _makexml.py 14 Jan 2005 14:28:00 -0000 1.4 *************** *** 3,6 **** --- 3,8 ---- import typedesc + import time + start = time.clock() # C keywords, according to MSDN, plus some additional *************** *** 234,242 **** ofi = create_file() MAGIC = """ ! #define DECLARE(sym) \ ! template <typename T> T symbol_##sym(T, T val = sym) {} - #define DEFINE(sym) \ - symbol_##sym(sym, sym) """ ofi.write(MAGIC) --- 236,242 ---- ofi = create_file() MAGIC = """ ! #define DECLARE(sym) template <typename T> T symbol_##sym(T) {} ! #define DEFINE(sym) symbol_##sym(sym) """ ofi.write(MAGIC) *************** *** 284,285 **** --- 284,287 ---- print "... finding preprocessor symbol values" os.system("gccxml glut.cpp -fxml=glut.xml") + + print "took %.2f seconds" % (time.clock() - start) |
From: Thomas H. <th...@us...> - 2005-01-14 14:15:15
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11614 Modified Files: _makexml.py Log Message: Refactoring. Added regular expressions for symbols to exclude, and INVALID_CHARS which cannot start or end a valid definition. Index: _makexml.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/_makexml.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** _makexml.py 14 Jan 2005 12:35:03 -0000 1.2 --- _makexml.py 14 Jan 2005 14:15:01 -0000 1.3 *************** *** 25,35 **** __noop""".split() - """ - PROPSHEETPAGEA_V1_FIELDS - PROPSHEETPAGEW_V1_FIELDS - """ - # defines we know that won't work ! EXCLUDED = """\ NOTIFYICONDATAA_V1_SIZE NOTIFYICONDATAA_V2_SIZE --- 25,30 ---- __noop""".split() # defines we know that won't work ! EXCLUDED = """ NOTIFYICONDATAA_V1_SIZE NOTIFYICONDATAA_V2_SIZE *************** *** 62,92 **** STDMETHODIMPV STDMETHODIMP - REFCLSID - REFFMTID - REFIID DEFAULT_UNREACHABLE MAXLONGLONG IMAGE_ORDINAL_FLAG64 SECURITY_NT_AUTHORITY ! FMTID_NULL ! IID_NULL ! CLSID_NULL ! ANONYMOUS_LOGON_LUID ! SYSTEM_LUID ! LOCALSERVICE_LUID ! SECURITY_RESOURCE_MANAGER_AUTHORITY ! SECURITY_NULL_SID_AUTHORITY ! SECURITY_CREATOR_SID_AUTHORITY ! SECURITY_WORLD_SID_AUTHORITY ! SECURITY_LOCAL_SID_AUTHORITY ! SECURITY_NON_UNIQUE_AUTHORITY ! NETWORKSERVICE_LUID ! REFGUID""".split() log = open("skipped.txt", "w") ! wordpat = re.compile("^[a-zA-Z_][a-zA-Z0-9_]*$") def _gccxml_get_defines(fname=None): cmd = "gccxml --preprocess -dM " if fname: --- 57,99 ---- STDMETHODIMPV STDMETHODIMP DEFAULT_UNREACHABLE MAXLONGLONG IMAGE_ORDINAL_FLAG64 SECURITY_NT_AUTHORITY ! """.strip().split() ! ! EXCLUDED = [text for text in EXCLUDED ! if not text.startswith("#")] ! ! EXCLUDED_RE = r""" ! ^DECLSPEC\w*$ ! """.strip().split() ! ! EXCLUDED_RE = [re.compile(pat) for pat in EXCLUDED_RE ! if not pat.startswith("#")] ! ! # One of these characters as first or last one of the definition will ! # give a syntax error when compiled, so it cannot be a value! ! INVALID_CHARS = "=/{};&" log = open("skipped.txt", "w") ! def is_excluded(name, value): ! if "(" in name: ! return "macro with parameters" ! if value in C_KEYWORDS: ! return "value is keyword" ! if name in EXCLUDED: ! return "excluded" ! for pat in EXCLUDED_RE: ! if pat.match(name): ! return "excluded (regex)" ! if value[0] in INVALID_CHARS or value[-1] in INVALID_CHARS: ! return "cannot be a value" ! return False def _gccxml_get_defines(fname=None): + # Helper for gccxml_get_defines. + # cmd = "gccxml --preprocess -dM " if fname: *************** *** 106,130 **** name, value = items ! if "(" in name: # we want only macros without parameters ! log.write("has params: #define %s %s\n" % (name, value)) ! continue ! ! if value in C_KEYWORDS: ! log.write("rhs is keyword: #define %s %s\n" % (name, value)) ! continue ! ! if name in EXCLUDED: ! log.write("excluded: #define %s %s\n" % (name, value)) ! continue ! ! # This is probably not correct: What when one of these characters is in a string literal? ! if value and value[0] in r"=/{};" \ ! or value and value[-1] in r"=/{};": ! log.write("won't work: #define %s %s\n" % (name, value)) ! continue ! ! if wordpat.match(name) and wordpat.match(value): ! # XXX aliases should be handled later, when (and if!) the rhs is known ! log.write("alias: #define %s %s\n" % (name, value)) continue --- 113,119 ---- name, value = items ! reason = is_excluded(name, value) ! if reason: ! log.write("%s: #define %s %s\n" % (reason, name, value)) continue *************** *** 180,191 **** print "... finding preprocessor symbol names" defs = gccxml_get_defines("glut.cpp") print "%d '#define' symbols found" % len(defs) ! names = set(defs.keys()) ! values = set(defs.values()) ! print "%d unique names, %d unique values" % (len(names), len(values)) ! print "removed %d aliases" % (len(names & values)) ! for n in (names & values): ! del defs[n] ################################################################ --- 169,190 ---- print "... finding preprocessor symbol names" defs = gccxml_get_defines("glut.cpp") + print "%d '#define' symbols found" % len(defs) ! def find_aliases(defs): ! aliases = {} ! wordpat = re.compile("^[a-zA-Z_][a-zA-Z0-9_]*$") ! for name in defs.keys(): ! value = defs[name] ! if wordpat.match(name) and wordpat.match(value): ! # aliases are handled later, when (and if!) the rhs is known ! ## log.write("alias: #define %s %s\n" % (name, value)) ! aliases[name] = defs[name] ! del defs[name] ! return aliases ! ! aliases = find_aliases(defs) ! ! print "%d symbols are name aliases" % len(aliases) ################################################################ *************** *** 229,237 **** defs = newdefs - for name in defs.keys(): - if name.startswith("DECLSPEC") or defs[name].startswith("DECLSPEC"): - del defs[name] - print "Remaining %s items after removing DECLSPEC..." % len(defs) - ################################################################ # invoke some C++ magic, which will create a lot of functions. --- 228,231 ---- |
From: Thomas H. <th...@us...> - 2005-01-14 12:35:15
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20969 Modified Files: _makexml.py Log Message: Works now *without* WIN32_LEAN_AND_MEAN defined. Index: _makexml.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/_makexml.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** _makexml.py 14 Jan 2005 10:54:53 -0000 1.1 --- _makexml.py 14 Jan 2005 12:35:03 -0000 1.2 *************** *** 1,3 **** ! import os from gccxmlparser import parse import typedesc --- 1,3 ---- ! import os, re from gccxmlparser import parse import typedesc *************** *** 5,37 **** # C keywords, according to MSDN, plus some additional ! # names like __forceinline, near and far. ! C_KEYWORDS = """__asm else main struct ! __assume enum __multiple_inheritance switch ! auto __except __single_inheritance template ! __based explicit __virtual_inheritance this ! bool extern mutable thread ! break false naked throw ! case __fastcall namespace true ! catch __finally new try ! __cdecl float noreturn __try ! char for operator typedef ! class friend private typeid ! const goto protected typename ! const_cast if public union ! continue inline register unsigned ! __declspec __inline ! default int return uuid ! delete __int8 short __uuidof ! dllexport __int16 signed virtual ! dllimport __int32 sizeof void ! do __int64 static volatile ! double __leave static_cast wmain ! dynamic_cast long __stdcall while ! far near __forceinline __w64 __noop""".split() ! # defines that won't work ! SKIPME = """STDAPI STDAPIV WINAPI APIENTRY EXTERN_C --- 5,60 ---- # C keywords, according to MSDN, plus some additional ! # names like __forceinline, near, far. ! # Skip all definitions where the rhs is a keyword ! # Example: #define CALLBACK __stdcall ! # ! # Hm, should types be handled differently? ! # Example: #define VOID void ! C_KEYWORDS = """__asm else main struct __assume enum ! __multiple_inheritance switch auto __except __single_inheritance ! template __based explicit __virtual_inheritance this bool extern ! mutable thread break false naked throw case __fastcall namespace true ! catch __finally new try __cdecl float noreturn __try char for operator ! typedef class friend private typeid const goto protected typename ! const_cast if public union continue inline register unsigned ! __declspec __inline default int return uuid delete __int8 short ! __uuidof dllexport __int16 signed virtual dllimport __int32 sizeof ! void do __int64 static volatile double __leave static_cast wmain ! dynamic_cast long __stdcall while far near __forceinline __w64 ! __noop""".split() ! ! """ ! PROPSHEETPAGEA_V1_FIELDS ! PROPSHEETPAGEW_V1_FIELDS ! """ ! ! # defines we know that won't work ! EXCLUDED = """\ ! NOTIFYICONDATAA_V1_SIZE ! NOTIFYICONDATAA_V2_SIZE ! PROPSHEETHEADERA_V1_SIZE ! PROPSHEETHEADERA_V2_SIZE ! PROPSHEETHEADERW_V2_SIZE ! NOTIFYICONDATAW_V2_SIZE ! s_imp ! s_host ! s_lh ! s_net ! s_addr ! h_addr ! s_impno ! _VARIANT_BOOL ! MIDL_uhyper ! WINSCARDDATA ! __MIDL_DECLSPEC_DLLIMPORT ! __MIDL_DECLSPEC_DLLEXPORT ! NCB_POST ! STDAPI STDAPIV WINAPI + SHDOCAPI + WINOLEAUTAPI + WINOLEAPI APIENTRY EXTERN_C *************** *** 61,79 **** REFGUID""".split() - # gccxml complains that these functions are undefined (?) - FUNC_MACROS = """CreateWindowA - CreateDialogA - DialogBoxA - PostAppMessageA - RtlZeroMemory - MAKEINTRESOURCEA - RtlMoveMemory - RtlCopyMemory - CreateDialogIndirectA - DialogBoxIndirectA - RtlFillMemory""".split() - log = open("skipped.txt", "w") def _gccxml_get_defines(fname=None): cmd = "gccxml --preprocess -dM " --- 84,91 ---- REFGUID""".split() log = open("skipped.txt", "w") + wordpat = re.compile("^[a-zA-Z_][a-zA-Z0-9_]*$") + def _gccxml_get_defines(fname=None): cmd = "gccxml --preprocess -dM " *************** *** 90,107 **** items = line.split(None, 1) if len(items) < 2: continue name, value = items if "(" in name: # we want only macros without parameters log.write("has params: #define %s %s\n" % (name, value)) continue if value in C_KEYWORDS: log.write("rhs is keyword: #define %s %s\n" % (name, value)) continue ! if name in SKIPME: log.write("won't work: #define %s %s\n" % (name, value)) continue ! if value in FUNC_MACROS: ! log.write("rhs is a function: #define %s %s\n" % (name, value)) continue result[name] = value return result --- 102,132 ---- items = line.split(None, 1) if len(items) < 2: + log.write("empty definition: #define %s\n" % items[0]) continue + name, value = items if "(" in name: # we want only macros without parameters log.write("has params: #define %s %s\n" % (name, value)) continue + if value in C_KEYWORDS: log.write("rhs is keyword: #define %s %s\n" % (name, value)) continue ! ! if name in EXCLUDED: ! log.write("excluded: #define %s %s\n" % (name, value)) ! continue ! ! # This is probably not correct: What when one of these characters is in a string literal? ! if value and value[0] in r"=/{};" \ ! or value and value[-1] in r"=/{};": log.write("won't work: #define %s %s\n" % (name, value)) continue ! ! if wordpat.match(name) and wordpat.match(value): ! # XXX aliases should be handled later, when (and if!) the rhs is known ! log.write("alias: #define %s %s\n" % (name, value)) continue + result[name] = value return result *************** *** 144,148 **** ofi = open("glut.cpp", "w") ## ofi.write('#include <gl/glut.h>\n') ! ofi.write("#define WIN32_LEAN_AND_MEAN\n") ofi.write('#include <windows.h>\n') return ofi --- 169,173 ---- ofi = open("glut.cpp", "w") ## ofi.write('#include <gl/glut.h>\n') ! # ofi.write("#define WIN32_LEAN_AND_MEAN\n") ofi.write('#include <windows.h>\n') return ofi |
From: Thomas H. <th...@us...> - 2005-01-14 10:55:04
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32121 Added Files: _makexml.py Log Message: This script does the same as h2xml.py - but also includes preprocessor definitions in the XML output. Not finished, ugly, wrongly named - BUT IT WORKS! Enough to check it inm, before working on it further. --- NEW FILE: _makexml.py --- import os from gccxmlparser import parse import typedesc # C keywords, according to MSDN, plus some additional # names like __forceinline, near and far. C_KEYWORDS = """__asm else main struct __assume enum __multiple_inheritance switch auto __except __single_inheritance template __based explicit __virtual_inheritance this bool extern mutable thread break false naked throw case __fastcall namespace true catch __finally new try __cdecl float noreturn __try char for operator typedef class friend private typeid const goto protected typename const_cast if public union continue inline register unsigned __declspec __inline default int return uuid delete __int8 short __uuidof dllexport __int16 signed virtual dllimport __int32 sizeof void do __int64 static volatile double __leave static_cast wmain dynamic_cast long __stdcall while far near __forceinline __w64 __noop""".split() # defines that won't work SKIPME = """STDAPI STDAPIV WINAPI APIENTRY EXTERN_C FIRMWARE_PTR STDMETHODIMPV STDMETHODIMP REFCLSID REFFMTID REFIID DEFAULT_UNREACHABLE MAXLONGLONG IMAGE_ORDINAL_FLAG64 SECURITY_NT_AUTHORITY FMTID_NULL IID_NULL CLSID_NULL ANONYMOUS_LOGON_LUID SYSTEM_LUID LOCALSERVICE_LUID SECURITY_RESOURCE_MANAGER_AUTHORITY SECURITY_NULL_SID_AUTHORITY SECURITY_CREATOR_SID_AUTHORITY SECURITY_WORLD_SID_AUTHORITY SECURITY_LOCAL_SID_AUTHORITY SECURITY_NON_UNIQUE_AUTHORITY NETWORKSERVICE_LUID REFGUID""".split() # gccxml complains that these functions are undefined (?) FUNC_MACROS = """CreateWindowA CreateDialogA DialogBoxA PostAppMessageA RtlZeroMemory MAKEINTRESOURCEA RtlMoveMemory RtlCopyMemory CreateDialogIndirectA DialogBoxIndirectA RtlFillMemory""".split() log = open("skipped.txt", "w") def _gccxml_get_defines(fname=None): cmd = "gccxml --preprocess -dM " if fname: cmd += fname i, o = os.popen4(cmd) i.close() result = {} for line in o: if not line.startswith("#define "): # Is this an error, should we print it? continue line = line[len("#define "):].strip() items = line.split(None, 1) if len(items) < 2: continue name, value = items if "(" in name: # we want only macros without parameters log.write("has params: #define %s %s\n" % (name, value)) continue if value in C_KEYWORDS: log.write("rhs is keyword: #define %s %s\n" % (name, value)) continue if name in SKIPME: log.write("won't work: #define %s %s\n" % (name, value)) continue if value in FUNC_MACROS: log.write("rhs is a function: #define %s %s\n" % (name, value)) continue result[name] = value return result def gccxml_get_defines(fname): """Find the preprocessor definitions in file <fname>. Do not return symbols defined as keywords, macros with parameters, or symbols defined by the C compiler itself.""" # find predefined symbols predefs = _gccxml_get_defines(None) # find defined symbols in this file defs = _gccxml_get_defines(fname) skipped = 0 for name in predefs: log.write("predefined compiler symbol: #define %s %s\n" % (name, defs[name])) del defs[name] skipped += 1 print "skipped %d predefined symbols" % skipped return defs def c_type_name(tp): """Return the C type name for this type. """ if isinstance(tp, typedesc.FundamentalType): return tp.name elif isinstance(tp, typedesc.PointerType): return "%s *" % c_type_name(tp.typ) elif isinstance(tp, typedesc.CvQualifiedType): return c_type_name(tp.typ) elif isinstance(tp, typedesc.Typedef): return c_type_name(tp.typ) elif isinstance(tp, typedesc.Structure): return tp.name raise TypeError, type(tp).__name__ ################################################################ def create_file(): ofi = open("glut.cpp", "w") ## ofi.write('#include <gl/glut.h>\n') ofi.write("#define WIN32_LEAN_AND_MEAN\n") ofi.write('#include <windows.h>\n') return ofi ################################################################ # parse a C header file, and dump the preprocessor symbols create_file() # find the preprocessor defined symbols print "... finding preprocessor symbol names" defs = gccxml_get_defines("glut.cpp") print "%d '#define' symbols found" % len(defs) names = set(defs.keys()) values = set(defs.values()) print "%d unique names, %d unique values" % (len(names), len(values)) print "removed %d aliases" % (len(names & values)) for n in (names & values): del defs[n] ################################################################ # parse the standard output print "... processing with gccxml" os.system("gccxml glut.cpp -fxml=glut.xml") print "... parsing gccxml output:", items = parse("glut.xml") print "%d type descriptions found" % len(items) types = {} for i in items: name = getattr(i, "name", None) if name: types[name] = i ##interesting = (typedesc.Function,) ##interesting = (typedesc.EnumValue,) interesting = (typedesc.FundamentalType, typedesc.Function, typedesc.FunctionType, typedesc.Typedef) # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX here continue to work... # filter the symbols ... newdefs = {} skipped = 0 known = set() for name, value in defs.iteritems(): if value in types: # Ah, we know the *type* and the *value* of this item already skipped += 1 ## print "SKIPPED", type(types[value]).__name__, name, value known.add(name) pass else: newdefs[name] = value print "skipped %d symbols, type and value are known from XML" % skipped print "Remaining %s items" % len(newdefs) defs = newdefs for name in defs.keys(): if name.startswith("DECLSPEC") or defs[name].startswith("DECLSPEC"): del defs[name] print "Remaining %s items after removing DECLSPEC..." % len(defs) ################################################################ # invoke some C++ magic, which will create a lot of functions. # The function name can later be used to retrieve the symbol name again, # and the function's return type is the symbols's type. ofi = create_file() MAGIC = """ #define DECLARE(sym) \ template <typename T> T symbol_##sym(T, T val = sym) {} #define DEFINE(sym) \ symbol_##sym(sym, sym) """ ofi.write(MAGIC) for name in defs: ofi.write("// #define %s %s\n" % (name, defs[name])) ofi.write("DECLARE(%s)\n" % name); ofi.write("int main() {\n") for name in defs: ofi.write(" DEFINE(%s);\n" % name); ofi.write("}\n") ofi.close() print "... finding preprocessor symbol types" # compile the file os.system("gccxml glut.cpp -fxml=glut.xml") # parse the result items = parse("glut.xml") # create a new C++ file which will later allow to retrieve the name, # the type and the value of the preprocessor definitions from the # gccxml created output. codelines = [] for i in items: if i.name and i.name.startswith("symbol_"): symname = i.name[len("symbol_"):] try: symtype = c_type_name(i.returns) except TypeError, detail: print "// skipped #define %s %s" % (symname, defs[symname]), detail # HWNDNOTOPMOST: ((HWND) -2), HWND is a structure continue codelines.append("const %s cpp_sym_%s = %s;" % (symtype, symname, symname)) print "created %d definitions" % len(codelines) ofi = create_file() for c in codelines: ofi.write("%s\n" % c) ofi.close() ################################################################ # parse the resulting file with gccxml, to create the xml that # will be used to generate Python code print "... finding preprocessor symbol values" os.system("gccxml glut.cpp -fxml=glut.xml") |
From: Thomas H. <th...@us...> - 2005-01-14 10:48:50
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30606 Modified Files: typedesc.py gccxmlparser.py codegenerator.py Log Message: The init property of Variables is optional. A hack to generate code for the init value. Index: typedesc.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/typedesc.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** typedesc.py 13 Jan 2005 16:43:42 -0000 1.5 --- typedesc.py 14 Jan 2005 10:48:39 -0000 1.6 *************** *** 139,143 **** class Variable(object): ! def __init__(self, name, typ, init): self.name = name self.typ = typ --- 139,143 ---- class Variable(object): ! def __init__(self, name, typ, init=None): self.name = name self.typ = typ Index: codegenerator.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/codegenerator.py,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -d -r1.20 -r1.21 *** codegenerator.py 13 Jan 2005 16:43:42 -0000 1.20 --- codegenerator.py 14 Jan 2005 10:48:39 -0000 1.21 *************** *** 143,146 **** --- 143,161 ---- return t.name + def init_value(t, init): + if isinstance(t, typedesc.CvQualifiedType): + return init_value(t.typ, init) + if isinstance(t, typedesc.FundamentalType): + name = ctypes_names[t.name] + if name in ("c_double", "c_float"): + return float(init) + if "unsigned" in t.name: + return int(init, 16) + return int(init) + if isinstance(t, typedesc.PointerType): + # XXXXXXXXXXXXXXXXX + return "pointer(%s)" % init_value(t.typ, init) + raise "HALT" + # Is this needed? ##renames = { *************** *** 257,261 **** self.done.add(tp) print >> self.stream, \ ! "%s = %s # Variable" % (tp.name, tp.init) def EnumValue(self, tp): --- 272,276 ---- self.done.add(tp) print >> self.stream, \ ! "%s = %s" % (tp.name, init_value(tp.typ, tp.init)) def EnumValue(self, tp): Index: gccxmlparser.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/gccxmlparser.py,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** gccxmlparser.py 13 Jan 2005 16:43:42 -0000 1.11 --- gccxmlparser.py 14 Jan 2005 10:48:39 -0000 1.12 *************** *** 73,77 **** # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx fix me! name = name[len("cpp_sym_"):] ! init = attrs["init"] typ = attrs["type"] return typedesc.Variable(name, typ, init) --- 73,77 ---- # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx fix me! name = name[len("cpp_sym_"):] ! init = attrs.get("init", None) typ = attrs["type"] return typedesc.Variable(name, typ, init) |
From: Thomas H. <th...@us...> - 2005-01-13 16:43:55
|
Update of /cvsroot/ctypes/ctypes/sandbox/tools/codegen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3247 Modified Files: typedesc.py gccxmlparser.py codegenerator.py Log Message: Add a variable type. Index: typedesc.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/typedesc.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** typedesc.py 12 Jan 2005 08:11:26 -0000 1.4 --- typedesc.py 13 Jan 2005 16:43:42 -0000 1.5 *************** *** 138,140 **** --- 138,146 ---- self.enumeration = enumeration + class Variable(object): + def __init__(self, name, typ, init): + self.name = name + self.typ = typ + self.init = init + ################################################################ Index: codegenerator.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/codegenerator.py,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -d -r1.19 -r1.20 *** codegenerator.py 12 Jan 2005 08:04:33 -0000 1.19 --- codegenerator.py 13 Jan 2005 16:43:42 -0000 1.20 *************** *** 252,255 **** --- 252,262 ---- self.done.add(tp) + def Variable(self, tp): + if tp in self.done: + return + self.done.add(tp) + print >> self.stream, \ + "%s = %s # Variable" % (tp.name, tp.init) + def EnumValue(self, tp): if tp in self.done: Index: gccxmlparser.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/sandbox/tools/codegen/gccxmlparser.py,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** gccxmlparser.py 12 Jan 2005 08:06:28 -0000 1.10 --- gccxmlparser.py 13 Jan 2005 16:43:42 -0000 1.11 *************** *** 58,62 **** def Namespace(self, attrs): pass - def Variable(self, attrs): pass def Base(self, attrs): pass def Ellipsis(self, attrs): pass --- 58,61 ---- *************** *** 69,72 **** --- 68,83 ---- # simple types and modifiers + def Variable(self, attrs): + name = attrs["name"] + if name.startswith("cpp_sym_"): + # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx fix me! + name = name[len("cpp_sym_"):] + init = attrs["init"] + typ = attrs["type"] + return typedesc.Variable(name, typ, init) + + def _fixup_Variable(self, t): + t.typ = self.all[t.typ] + def Typedef(self, attrs): name = self.demangle(attrs["name"]) *************** *** 260,264 **** def get_result(self): interesting = (typedesc.Typedef, typedesc.Enumeration, typedesc.EnumValue, ! typedesc.Function, typedesc.Structure, typedesc.Union) result = [] remove = [] --- 271,276 ---- def get_result(self): interesting = (typedesc.Typedef, typedesc.Enumeration, typedesc.EnumValue, ! typedesc.Function, typedesc.Structure, typedesc.Union, ! typedesc.Variable) result = [] remove = [] *************** *** 284,286 **** xml.sax.parse(xmlfile, handler) return handler.get_result() - --- 296,297 ---- |
From: Thomas H. <th...@us...> - 2005-01-13 09:38:05
|
Update of /cvsroot/ctypes/ctypes/comtypes/unittests In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17275 Modified Files: test_basic.py Log Message: Removed the _nummethods_ property, replaced by a mechanism to calculate it. Changed the requirements for COM method implementations. - The method body is optional now. - If a method body is given, it must call the actual COM method like this: 'self.<methodname>._api_(self, *args)' Index: test_basic.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/comtypes/unittests/test_basic.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** test_basic.py 12 Jan 2005 20:54:05 -0000 1.1 --- test_basic.py 13 Jan 2005 09:37:49 -0000 1.2 *************** *** 1,10 **** import unittest ! from ctypes import windll, POINTER, byref ! from comtypes import IUnknown class BasicTest(unittest.TestCase): def test_IUnknown(self): from comtypes import IUnknown ! self.failUnlessEqual(IUnknown._nummethods_, 3) def test_release(self): --- 1,14 ---- import unittest ! from ctypes import windll, POINTER, byref, HRESULT ! from comtypes import IUnknown, STDMETHOD ! ! def method_count(interface): ! return sum([len(base.__dict__.get("_methods_", ())) ! for base in interface.__mro__]) class BasicTest(unittest.TestCase): def test_IUnknown(self): from comtypes import IUnknown ! self.failUnlessEqual(method_count(IUnknown), 3) def test_release(self): *************** *** 39,49 **** def test_derived(self): class IMyInterface(IUnknown): pass ! self.failUnlessEqual(IMyInterface._nummethods_, 3) IMyInterface._methods_ = [] ! self.failUnlessEqual(IMyInterface._nummethods_, 3) def test_mro(self): --- 43,59 ---- def test_derived(self): + self.failUnlessEqual(method_count(IUnknown), 3) + class IMyInterface(IUnknown): pass ! self.failUnlessEqual(method_count(IMyInterface), 3) IMyInterface._methods_ = [] ! self.failUnlessEqual(method_count(IMyInterface), 3) ! ! IMyInterface._methods_ = [ ! STDMETHOD(HRESULT, "Blah", [])] ! self.failUnlessEqual(method_count(IMyInterface), 4) def test_mro(self): *************** *** 56,59 **** --- 66,101 ---- self.failUnless(IUnknown.__dict__.get("QueryInterface")) + ## def test_identity(self): + ## p = POINTER(IUnknown)() + #### p[0] + ## windll.oleaut32.CreateTypeLib(1, u"blabla", byref(p)) + + ## p = p.QueryInterface(IUnknown) + ## other = p.QueryInterface(IUnknown) + + ## print other == p + ## print other is p + ## print "A" + ## print "?", p[0] + ## print "B" + #### p[0] = 42 + ## print "C" + ## print dir(p) + ## from ctypes import cast, c_int + ## print cast(other, c_int).value + ## print cast(p, c_int).value + + ## x = POINTER(IUnknown)() + ## windll.oleaut32.CreateTypeLib(1, u"blabla_2", byref(x)) + ## x = x.QueryInterface(IUnknown) + + ## print cast(x, c_int).value + + ## print "D" + ## del p + ## print "E" + ## del other + ## print "F" + if __name__ == "__main__": unittest.main() |
From: Thomas H. <th...@us...> - 2005-01-13 09:34:57
|
Update of /cvsroot/ctypes/ctypes/comtypes In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16733 Modified Files: __init__.py Log Message: Removed the _nummethods_ property, replaced by a mechanism to calculate it. Changed the requirements for COM method implementations. - The method body is optional now. - If a method body is given, it must call the actual COM method like this: 'self.<methodname>._api_(self, *args)' Index: __init__.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/comtypes/__init__.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** __init__.py 12 Jan 2005 20:53:51 -0000 1.1 --- __init__.py 13 Jan 2005 09:34:45 -0000 1.2 *************** *** 13,16 **** --- 13,40 ---- #_pbase = c_void_p + def _create_method_codestring(func, doc=None): + # Assuming the <func> has this definition: + # def func(self, first, second="spam", third=42): + # .... + # a string containing the following code is returned: + # def func(self, first, second="spam", third=42): + # return self.func._api_(self, first, second, third) + import inspect + args, varargs, varkw, defaults = inspect.getargspec(func) + if varkw: + raise TypeError, "%s argument list must not contain ** argument" % func.func_name + if doc: + return "def %s%s:\n %r\n return self.%s._api_%s" % \ + (func.func_name, + inspect.formatargspec(args, varargs, varkw, defaults), + doc, + func.func_name, + inspect.formatargspec(args, varargs, varkw)) + return "def %s%s:\n return self.%s._api_%s" % \ + (func.func_name, + inspect.formatargspec(args, varargs, varkw, defaults), + func.func_name, + inspect.formatargspec(args, varargs, varkw)) + class _cominterface_meta(type): # Metaclass for COM interface classes. *************** *** 23,34 **** # The interface 'cls' is used as a mixin for the # POINTER(interface) class: ! def __del__(cls): "Release the COM refcount we own." ! if cls: ! result = cls.Release() # POINTER(interface) looks nice as class name, but is it ok? p = _compointer_meta("POINTER(%s)" % cls.__name__, (cls, _pbase), ! {"__del__": __del__}) from ctypes import _pointer_type_cache _pointer_type_cache[cls] = p --- 47,63 ---- # The interface 'cls' is used as a mixin for the # POINTER(interface) class: ! def __del__(s_): "Release the COM refcount we own." ! if s_: ! result = s_.Release() ! ## def __eq__(s_, other): ! ## return cast(s_, c_int).value == cast(other, c_int).value # POINTER(interface) looks nice as class name, but is it ok? p = _compointer_meta("POINTER(%s)" % cls.__name__, (cls, _pbase), ! {"__del__": __del__, ! ## "__eq__": __eq__, # XXX fixme: COM identity rules ! "_type_": c_int # XXX fixme ! }) from ctypes import _pointer_type_cache _pointer_type_cache[cls] = p *************** *** 41,69 **** self.make_methods(value) def make_methods(self, methods): ! from deco import _make_constants ! basemethods = getattr(self.__bases__[0], "_nummethods_", 0) ! if methods: ! for i, (restype, name, argtypes) in enumerate(methods): ! #print i + basemethods, name ! # the function prototype ! prototype = WINFUNCTYPE(restype, *argtypes) ! # the actual COM interface method object, will invoke ! # the method in the VTable of the COM interface pointer ! func = prototype(i + basemethods, name) ! # the Python method implementation in te interface ! mth = getattr(self, name, None) ! if mth is None: ! mth = _default_implementation ! else: ! mth = mth.im_func ! # replace the _api_ global by the COM method callable ! mth = _make_constants(mth, _api_=func) ! # replace the Python implementation by our 'decorated' function ! setattr(self, name, mth) ! self._nummethods_ = basemethods + i + 1 ! else: ! self._nummethods_ = basemethods # This class only to avoid a metaclass confict. No additional --- 70,115 ---- self.make_methods(value) + def __get_method(self, name): + # should create a method if doesn't have one. + mth = getattr(self, name, None) + if mth is None: + def func(self, *args): + return getattr(self, name)._api_(self, *args) + setattr(self, name, func) + # convert into unbound method + mth = getattr(self, name) + return mth + + func = mth.im_func + if len(func.func_code.co_code) == 4: + # method has no body - create one + codestring = _create_method_codestring(func, func.func_doc) + ns = {} + exec codestring in ns + func = ns[func.func_name] + # convert into unbound method + setattr(self, name, func) + mth = getattr(self, name) + return mth + + def __get_baseinterface_methodcount(self): + "Return the number of com methods in the base interfaces" + return sum([len(itf.__dict__.get("_methods_", ())) + for itf in self.__mro__[1:]]) + def make_methods(self, methods): ! if not methods: ! return ! vtbl_offset = self.__get_baseinterface_methodcount() ! for i, (restype, name, argtypes) in enumerate(methods): ! # the function prototype ! prototype = WINFUNCTYPE(restype, *argtypes) ! # the actual COM interface method object, will invoke ! # the method in the VTable of the COM interface pointer ! func = prototype(i + vtbl_offset, name) ! # the Python method implementation in the interface ! mth = self.__get_method(name) ! mth.im_func._api_ = func # This class only to avoid a metaclass confict. No additional *************** *** 72,79 **** pass - def _default_implementation(self, *args): - # Default COM client method - return _api_(self, *args) - ################################################################ --- 118,121 ---- *************** *** 91,95 **** "QueryInterface(klass) -> instance" p = POINTER(interface)() ! _api_(self, byref(interface._iid_), byref(p)) return p --- 133,137 ---- "QueryInterface(klass) -> instance" p = POINTER(interface)() ! self.QueryInterface._api_(self, byref(interface._iid_), byref(p)) return p *************** *** 107,110 **** ] if __name__ == "__main__": ! print help(POINTER(IUnknown)) --- 149,154 ---- ] + __all__ = "IUnknown GUID HRESULT BSTR STDMETHOD".split() + if __name__ == "__main__": ! help(POINTER(IUnknown)) |
From: Thomas H. <th...@us...> - 2005-01-12 20:54:15
|
Update of /cvsroot/ctypes/ctypes/comtypes/unittests In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28228 Added Files: test_basic.py runtests.py .cvsignore Log Message: comtypes is advanced enough to be checked in. Not that it really works, though ;-) --- NEW FILE: .cvsignore --- test_basic.pyc --- NEW FILE: test_basic.py --- import unittest from ctypes import windll, POINTER, byref from comtypes import IUnknown class BasicTest(unittest.TestCase): def test_IUnknown(self): from comtypes import IUnknown self.failUnlessEqual(IUnknown._nummethods_, 3) def test_release(self): POINTER(IUnknown)() def test_refcounts(self): p = POINTER(IUnknown)() windll.oleaut32.CreateTypeLib(1, u"blabla", byref(p)) # initial refcount is 2 for i in range(2, 10): self.failUnlessEqual(p.AddRef(), i) for i in range(8, 0, -1): self.failUnlessEqual(p.Release(), i) def test_qi(self): p = POINTER(IUnknown)() windll.oleaut32.CreateTypeLib(1, u"blabla", byref(p)) self.failUnlessEqual(p.AddRef(), 2) self.failUnlessEqual(p.Release(), 1) other = p.QueryInterface(IUnknown) self.failUnlessEqual(other.AddRef(), 3) self.failUnlessEqual(p.AddRef(), 4) self.failUnlessEqual(p.Release(), 3) self.failUnlessEqual(other.Release(), 2) del p # calls p.Release() self.failUnlessEqual(other.AddRef(), 2) self.failUnlessEqual(other.Release(), 1) def test_derived(self): class IMyInterface(IUnknown): pass self.failUnlessEqual(IMyInterface._nummethods_, 3) IMyInterface._methods_ = [] self.failUnlessEqual(IMyInterface._nummethods_, 3) def test_mro(self): mro = POINTER(IUnknown).__mro__ self.failUnlessEqual(mro[0], POINTER(IUnknown)) self.failUnlessEqual(mro[1], IUnknown) # the IUnknown class has the actual methods: self.failUnless(IUnknown.__dict__.get("QueryInterface")) if __name__ == "__main__": unittest.main() --- NEW FILE: runtests.py --- """Usage: runtests.py [-q] [-v] [mask] Run all tests found in this directory, and print a summary of the results. Command line flags: -v verbose mode: print the test currently executed -q quiet mode: don't prnt anything while the tests are running mask mask to select filenames containing testcases, wildcards allowed """ import glob, os, sys, unittest, getopt def get_suite(mask): if not mask.endswith(".py"): mask += ".py" test_suites = [] for fname in glob.glob(mask): try: mod = __import__(os.path.splitext(fname)[0]) except Exception, detail: print "Warning: could not import %s: %s" % (fname, detail) continue for name in dir(mod): if name.startswith("_"): continue o = getattr(mod, name) if type(o) is type(unittest.TestCase) and issubclass(o, unittest.TestCase): test_suites.append(unittest.makeSuite(o)) return unittest.TestSuite(test_suites) def usage(): print __doc__ return 1 def main(): verbosity = 1 mask = "test_*.py" try: opts, args = getopt.getopt(sys.argv[1:], "qv") except getopt.error: return usage() for flag, value in opts: if flag == "-q": verbosity -= 1 elif flag == "-v": verbosity += 1 if args: mask = args[0] suite = get_suite(mask) runner = unittest.TextTestRunner(verbosity=verbosity) return bool(runner.run(suite).errors) if __name__ == "__main__": sys.exit(main()) |
From: Thomas H. <th...@us...> - 2005-01-12 20:54:03
|
Update of /cvsroot/ctypes/ctypes/comtypes In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28035 Added Files: __init__.py GUID.py BSTR.py Log Message: comtypes is advanced enough to be checked in. Not that it really works, though ;-) --- NEW FILE: BSTR.py --- ################################################################ # Memory mamagement of BSTR is broken. # # The way we do them here, it is not possible to transfer the # ownership of a BSTR instance. ctypes allocates the memory with # SysAllocString if we call the constructor with a string, and the # instance calls SysFreeString when it is destroyed. # So BSTR's received from dll function calls will never be freed, # and BSTR's we pass to functions are freed too often ;-( from ctypes import sizeof, _SimpleCData class BSTR(_SimpleCData): _type_ = "X" def __repr__(self): return "%s(%r)" % (self.__class__.__name__, self.value) assert(sizeof(BSTR) == 4) --- NEW FILE: GUID.py --- from ctypes import * from ctypes.wintypes import DWORD, WORD, BYTE _ole32 = oledll.ole32 class GUID(Structure): _fields_ = [("Data1", DWORD), ("Data2", WORD), ("Data3", WORD), ("Data4", BYTE * 8)] def __init__(self, name=None): if name is not None: _ole32.CLSIDFromString(unicode(name), byref(self)) def __repr__(self): s = (c_wchar * 39)() _ole32.StringFromGUID2(byref(self), s, 39) return 'GUID("%s")' % s.value def __str__(self): s = (c_wchar * 39)() _ole32.StringFromGUID2(byref(self), s, 39) return s.value def __cmp__(self, other): if isinstance(other, GUID): return not _ole32.IsEqualGUID(byref(self), byref(other)) return -1 def __nonzero__(self): result = str(buffer(self)) != "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" return result def __eq__(self, other): return isinstance(other, GUID) and \ _ole32.IsEqualGUID(byref(self), byref(other)) ## def __hash__(self): ## return hash(repr(self)) def copy(self): return GUID(str(self)) def from_progid(cls, progid): inst = cls() _ole32.CLSIDFromProgID(unicode(progid), byref(inst)) return inst from_progid = classmethod(from_progid) assert(sizeof(GUID) == 16), sizeof(GUID) --- NEW FILE: __init__.py --- from ctypes import * try: HRESULT except NameError: # ctypes 0.92 and older from _ctypes import HRESULT from comtypes.GUID import GUID ################################################################ # The metaclasses... # would c_void_p be a better base? Conflicts with the QueryInterface signature... _pbase = POINTER(c_void_p) #_pbase = c_void_p class _cominterface_meta(type): # Metaclass for COM interface classes. # Creates POINTER(cls) also for the newly created class. def __new__(self, name, bases, namespace): methods = namespace.pop("_methods_", None) cls = type.__new__(self, name, bases, namespace) if methods: setattr(cls, "_methods_", methods) # The interface 'cls' is used as a mixin for the # POINTER(interface) class: def __del__(cls): "Release the COM refcount we own." if cls: result = cls.Release() # POINTER(interface) looks nice as class name, but is it ok? p = _compointer_meta("POINTER(%s)" % cls.__name__, (cls, _pbase), {"__del__": __del__}) from ctypes import _pointer_type_cache _pointer_type_cache[cls] = p return cls def __setattr__(self, name, value): type.__setattr__(self, name, value) if name != "_methods_": return self.make_methods(value) def make_methods(self, methods): from deco import _make_constants basemethods = getattr(self.__bases__[0], "_nummethods_", 0) if methods: for i, (restype, name, argtypes) in enumerate(methods): #print i + basemethods, name # the function prototype prototype = WINFUNCTYPE(restype, *argtypes) # the actual COM interface method object, will invoke # the method in the VTable of the COM interface pointer func = prototype(i + basemethods, name) # the Python method implementation in te interface mth = getattr(self, name, None) if mth is None: mth = _default_implementation else: mth = mth.im_func # replace the _api_ global by the COM method callable mth = _make_constants(mth, _api_=func) # replace the Python implementation by our 'decorated' function setattr(self, name, mth) self._nummethods_ = basemethods + i + 1 else: self._nummethods_ = basemethods # This class only to avoid a metaclass confict. No additional # behaviour here. class _compointer_meta(type(_pbase), _cominterface_meta): pass def _default_implementation(self, *args): # Default COM client method return _api_(self, *args) ################################################################ from comtypes.BSTR import BSTR def STDMETHOD(restype, name, argtypes=()): "Defines a COM method" return restype, name, argtypes class IUnknown(object): __metaclass__ = _cominterface_meta _iid_ = GUID("{00000000-0000-0000-C000-000000000046}") def QueryInterface(self, interface): "QueryInterface(klass) -> instance" p = POINTER(interface)() _api_(self, byref(interface._iid_), byref(p)) return p def AddRef(self): "Increase the internal refcount by one" def Release(self): "Decrease the internal refcount by one" _methods_ = [ STDMETHOD(HRESULT, "QueryInterface", [POINTER(GUID), POINTER(_pbase)]), STDMETHOD(c_ulong, "AddRef"), STDMETHOD(c_ulong, "Release") ] if __name__ == "__main__": print help(POINTER(IUnknown)) |
From: Thomas H. <th...@us...> - 2005-01-12 20:50:17
|
Update of /cvsroot/ctypes/ctypes/comtypes/unittests In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27092/unittests Log Message: Directory /cvsroot/ctypes/ctypes/comtypes/unittests added to the repository |