PyXR

c:\python24\lib\site-packages\win32 \ com \ makegw \ makegwparse.py



0001 """Utilities for makegw - Parse a header file to build an interface
0002 
0003  This module contains the core code for parsing a header file describing a
0004  COM interface, and building it into an "Interface" structure.
0005 
0006  Each Interface has methods, and each method has arguments.
0007 
0008  Each argument knows how to use Py_BuildValue or Py_ParseTuple to
0009  exchange itself with Python.
0010  
0011  See the @win32com.makegw@ module for information in building a COM
0012  interface
0013 """
0014 import regex
0015 import traceback
0016 import string
0017 
0018 error_not_found = "The requested item could not be found"
0019 error_not_supported = "The required functionality is not supported"
0020 
0021 VERBOSE=0
0022 DEBUG=0
0023 
0024 ## NOTE : For interfaces as params to work correctly, you must
0025 ## make sure any PythonCOM extensions which expose the interface are loaded
0026 ## before generating.
0027 
0028 
0029 class ArgFormatter:
0030         """An instance for a specific type of argument.     Knows how to convert itself"""
0031         def __init__(self, arg, builtinIndirection, declaredIndirection = 0):
0032                 #print 'init:', arg.name, builtinIndirection, declaredIndirection, arg.indirectionLevel
0033                 self.arg = arg
0034                 self.builtinIndirection = builtinIndirection
0035                 self.declaredIndirection = declaredIndirection
0036                 self.gatewayMode = 0
0037         def _IndirectPrefix(self, indirectionFrom, indirectionTo):
0038                 """Given the indirection level I was declared at (0=Normal, 1=*, 2=**)
0039                 return a string prefix so I can pass to a function with the
0040                 required indirection (where the default is the indirection of the method's param.
0041                 
0042                 eg, assuming my arg has indirection level of 2, if this function was passed 1
0043                 it would return "&", so that a variable declared with indirection of 1
0044                 can be prefixed with this to turn it into the indirection level required of 2
0045                 """
0046                 dif = indirectionFrom - indirectionTo
0047                 if dif==0:
0048                   return ""
0049                 elif dif==-1:
0050                   return "&"
0051                 elif dif==1:
0052                   return "*"
0053                 else:
0054                   return "??"
0055                   raise error_not_supported, "Can't indirect this far - please fix me :-)"
0056         def GetIndirectedArgName(self, indirectFrom, indirectionTo):
0057                 #print 'get:',self.arg.name, indirectFrom,self._GetDeclaredIndirection() + self.builtinIndirection, indirectionTo, self.arg.indirectionLevel
0058 
0059                 if indirectFrom is None:
0060                         ### ACK! this does not account for [in][out] variables.
0061                         ### when this method is called, we need to know which
0062                         indirectFrom = self._GetDeclaredIndirection() + self.builtinIndirection
0063 
0064                 return self._IndirectPrefix(indirectFrom, indirectionTo) + self.arg.name
0065         def GetBuildValueArg(self):
0066                 "Get the argument to be passes to Py_BuildValue"
0067                 return self.arg.name
0068         def GetParseTupleArg(self):
0069                 "Get the argument to be passed to PyArg_ParseTuple"
0070                 if self.gatewayMode:
0071                         # use whatever they were declared with
0072                         return self.GetIndirectedArgName(None, 1)
0073                 # local declarations have just their builtin indirection
0074                 return self.GetIndirectedArgName(self.builtinIndirection, 1)
0075         def GetInterfaceCppObjectInfo(self):
0076                 """Provide information about the C++ object used.
0077                                 
0078                 Simple variables (such as integers) can declare their type (eg an integer)
0079                 and use it as the target of both PyArg_ParseTuple and the COM function itself.
0080                 
0081                 More complex types require a PyObject * declared as the target of PyArg_ParseTuple,
0082                 then some conversion routine to the C++ object which is actually passed to COM.
0083                 
0084                 This method provides the name, and optionally the type of that C++ variable.  
0085                 If the type if provided, the caller will likely generate a variable declaration.
0086                 The name must always be returned.
0087                 
0088                 Result is a tuple of (variableName, [DeclareType|None|""])
0089                 """
0090 
0091                 # the first return element is the variable to be passed as
0092                 #  an argument to an interface method. the variable was
0093                 #  declared with only its builtin indirection level. when
0094                 #  we pass it, we'll need to pass in whatever amount of
0095                 #  indirection was applied (plus the builtin amount)
0096                 # the second return element is the variable declaration; it
0097                 #  should simply be builtin indirection
0098                 return self.GetIndirectedArgName(self.builtinIndirection, self.arg.indirectionLevel + self.builtinIndirection), \
0099                                            "%s %s" % (self.GetUnconstType(), self.arg.name)
0100 
0101         def GetInterfaceArgCleanup(self):
0102                 "Return cleanup code for C++ args passed to the interface method."
0103                 if DEBUG:
0104                         return "/* GetInterfaceArgCleanup output goes here: %s */\n" % self.arg.name
0105                 else:
0106                         return ""
0107 
0108         def GetInterfaceArgCleanupGIL(self):
0109                 """Return cleanup code for C++ args passed to the interface
0110                 method that must be executed with the GIL held"""
0111                 if DEBUG:
0112                         return "/* GetInterfaceArgCleanup (GIL held) output goes here: %s */\n" % self.arg.name
0113                 else:
0114                         return ""
0115 
0116         def GetUnconstType(self):
0117                 return self.arg.unc_type
0118         
0119         def SetGatewayMode(self):
0120                 self.gatewayMode = 1
0121         def _GetDeclaredIndirection(self):
0122                 return self.arg.indirectionLevel
0123                 print 'declared:', self.arg.name, self.gatewayMode
0124                 if self.gatewayMode:
0125                         return self.arg.indirectionLevel
0126                 else:
0127                         return self.declaredIndirection
0128         def DeclareParseArgTupleInputConverter(self):
0129                 "Declare the variable used as the PyArg_ParseTuple param for a gateway"
0130                 # Only declare it??
0131                 #if self.arg.indirectionLevel==0:
0132                 # return "\t%s %s;\n" % (self.arg.type, self.arg.name)
0133                 #else:
0134                 if DEBUG:
0135                         return "/* Declare ParseArgTupleInputConverter goes here: %s */\n" % self.arg.name
0136                 else:
0137                         return ""
0138         def GetParsePostCode(self):
0139                 "Get a string of C++ code to be executed after (ie, to finalise) the PyArg_ParseTuple conversion"
0140                 if DEBUG:
0141                         return "/* GetParsePostCode code goes here: %s */\n" % self.arg.name
0142                 else:
0143                         return ""
0144         def GetBuildForInterfacePreCode(self):
0145                 "Get a string of C++ code to be executed before (ie, to initialise) the Py_BuildValue conversion for Interfaces"
0146                 if DEBUG:
0147                         return "/* GetBuildForInterfacePreCode goes here: %s */\n" % self.arg.name
0148                 else:
0149                         return ""
0150         def GetBuildForGatewayPreCode(self):
0151                 "Get a string of C++ code to be executed before (ie, to initialise) the Py_BuildValue conversion for Gateways"
0152                 s = self.GetBuildForInterfacePreCode() # Usually the same
0153                 if DEBUG:
0154                         if s[:4] == "/* G":
0155                                 s = "/* GetBuildForGatewayPreCode goes here: %s */\n" % self.arg.name
0156                 return s
0157         def GetBuildForInterfacePostCode(self):
0158                 "Get a string of C++ code to be executed after (ie, to finalise) the Py_BuildValue conversion for Interfaces"
0159                 if DEBUG:
0160                         return "/* GetBuildForInterfacePostCode goes here: %s */\n" % self.arg.name
0161                 return ""
0162         def GetBuildForGatewayPostCode(self):
0163                 "Get a string of C++ code to be executed after (ie, to finalise) the Py_BuildValue conversion for Gateways"
0164                 s = self.GetBuildForInterfacePostCode() # Usually the same
0165                 if DEBUG:
0166                         if s[:4] == "/* G":
0167                                 s = "/* GetBuildForGatewayPostCode goes here: %s */\n" % self.arg.name
0168                 return s
0169         def GetAutoduckString(self):
0170                 return '// @pyparm %s|%s||Description for %s' % (self._GetPythonTypeDesc(), self.arg.name, self.arg.name)
0171         def _GetPythonTypeDesc(self):
0172                 "Returns a string with the description of the type.         Used for doco purposes"
0173                 return None
0174         def NeedUSES_CONVERSION(self):
0175                 "Determines if this arg forces a USES_CONVERSION macro"
0176                 return 0
0177 
0178 # Special formatter for floats since they're smaller than Python floats.
0179 class ArgFormatterFloat(ArgFormatter):
0180         def GetFormatChar(self):
0181                 return "f"
0182         def DeclareParseArgTupleInputConverter(self):
0183                 # Declare a double variable
0184                 return "\tdouble dbl%s;\n" % self.arg.name
0185         def GetParseTupleArg(self):
0186                 return "&dbl" + self.arg.name
0187         def _GetPythonTypeDesc(self):
0188                 return "float"
0189         def GetBuildValueArg(self):
0190                 return "&dbl" + self.arg.name
0191         def GetBuildForInterfacePreCode(self):
0192                 return "\tdbl" + self.arg.name + " = " + self.arg.name + ";\n"
0193         def GetBuildForGatewayPreCode(self):
0194                 return "\tdbl%s = " % self.arg.name + self._IndirectPrefix( \
0195                         self._GetDeclaredIndirection(),
0196                         0) + self.arg.name + ";\n"
0197         def GetParsePostCode(self):
0198                 s = "\t"
0199                 if self.gatewayMode:
0200                         s = s + self._IndirectPrefix( 
0201                                 self._GetDeclaredIndirection(),
0202                                 0)
0203                 s = s + self.arg.name
0204                 s = s + " = (float)dbl%s;\n" % self.arg.name
0205                 return s
0206 
0207 # Special formatter for Shorts because they're
0208 # a different size than Python ints!
0209 class ArgFormatterShort(ArgFormatter):
0210         def GetFormatChar(self):
0211                 return "i"
0212         def DeclareParseArgTupleInputConverter(self):
0213                 # Declare a double variable
0214                 return "\tINT i%s;\n" % self.arg.name
0215         def GetParseTupleArg(self):
0216                 return "&i" + self.arg.name
0217         def _GetPythonTypeDesc(self):
0218                 return "int"
0219         def GetBuildValueArg(self):
0220                 return "&i" + self.arg.name
0221         def GetBuildForInterfacePreCode(self):
0222                 return "\ti" + self.arg.name + " = " + self.arg.name + ";\n"
0223         def GetBuildForGatewayPreCode(self):
0224                 return "\ti%s = " % self.arg.name + self._IndirectPrefix( \
0225                         self._GetDeclaredIndirection(),
0226                         0) + self.arg.name + ";\n"
0227         def GetParsePostCode(self):
0228                 s = "\t"
0229                 if self.gatewayMode:
0230                         s = s + self._IndirectPrefix( 
0231                                 self._GetDeclaredIndirection(),
0232                                 0)
0233                 s = s + self.arg.name
0234                 s = s + " = i%s;\n" % self.arg.name
0235                 return s
0236 
0237 class ArgFormatterPythonCOM(ArgFormatter):
0238         """An arg formatter for types exposed in the PythonCOM module"""
0239         def GetFormatChar(self):
0240                 return "O"
0241         #def GetInterfaceCppObjectInfo(self):
0242         # return ArgFormatter.GetInterfaceCppObjectInfo(self)[0], \
0243         #         "%s %s%s" % (self.arg.unc_type, "*" * self._GetDeclaredIndirection(), self.arg.name)
0244         def DeclareParseArgTupleInputConverter(self):
0245                 # Declare a PyObject variable
0246                 return "\tPyObject *ob%s;\n" % self.arg.name
0247         def GetParseTupleArg(self):
0248                 return "&ob"+self.arg.name
0249         def _GetPythonTypeDesc(self):
0250                 return "<o Py%s>" % self.arg.type
0251         def GetBuildValueArg(self):
0252                 return "ob" + self.arg.name
0253         def GetBuildForInterfacePostCode(self):
0254                 return "\tPy_XDECREF(ob%s);\n" % self.arg.name
0255         def DeclareParseArgTupleInputConverter(self):
0256                 # Declare a PyObject variable
0257                 return "\tPyObject *ob%s;\n" % self.arg.name
0258 
0259 class ArgFormatterBSTR(ArgFormatterPythonCOM):
0260         def _GetPythonTypeDesc(self):
0261                 return "<o unicode>"
0262         def GetParsePostCode(self):
0263                 return "\tif (bPythonIsHappy && !PyWinObject_AsBstr(ob%s, %s)) bPythonIsHappy = FALSE;\n" % (self.arg.name, self.GetIndirectedArgName(None, 2))
0264         def GetBuildForInterfacePreCode(self):
0265                 notdirected = self.GetIndirectedArgName(None, 1)
0266                 return "\tob%s = MakeBstrToObj(%s);\n" % \
0267                            (self.arg.name, notdirected)
0268         def GetBuildForInterfacePostCode(self):
0269                 return "\tSysFreeString(%s);\n" % (self.arg.name,) + \
0270                        ArgFormatterPythonCOM.GetBuildForInterfacePostCode(self)
0271         def GetBuildForGatewayPostCode(self):
0272                 return "\tPy_XDECREF(ob%s);\n" % self.arg.name
0273 
0274 class ArgFormatterOLECHAR(ArgFormatterPythonCOM):
0275         def _GetPythonTypeDesc(self):
0276                 return "<o unicode>"
0277         def GetUnconstType(self):
0278                 if self.arg.type[:3]=="LPC":
0279                         return self.arg.type[:2] + self.arg.type[3:]
0280                 else:
0281                         return self.arg.unc_type
0282         def GetParsePostCode(self):
0283                 return "\tif (bPythonIsHappy && !PyWinObject_AsBstr(ob%s, %s)) bPythonIsHappy = FALSE;\n" % (self.arg.name, self.GetIndirectedArgName(None, 2))
0284         def GetInterfaceArgCleanup(self):
0285                 return "\tSysFreeString(%s);\n" % self.GetIndirectedArgName(None, 1)
0286         def GetBuildForInterfacePreCode(self):
0287                 # the variable was declared with just its builtin indirection
0288                 notdirected = self.GetIndirectedArgName(self.builtinIndirection, 1)
0289                 return "\tob%s = MakeOLECHARToObj(%s);\n" % \
0290                            (self.arg.name, notdirected)
0291         def GetBuildForInterfacePostCode(self):
0292                 # memory returned into an OLECHAR should be freed
0293                 return "\tCoTaskMemFree(%s);\n" % (self.arg.name,) + \
0294                        ArgFormatterPythonCOM.GetBuildForInterfacePostCode(self)
0295         def GetBuildForGatewayPostCode(self):
0296                 return "\tPy_XDECREF(ob%s);\n" % self.arg.name
0297 
0298 class ArgFormatterTCHAR(ArgFormatterPythonCOM):
0299         def _GetPythonTypeDesc(self):
0300                 return "string/<o unicode>"
0301         def GetUnconstType(self):
0302                 if self.arg.type[:3]=="LPC":
0303                         return self.arg.type[:2] + self.arg.type[3:]
0304                 else:
0305                         return self.arg.unc_type
0306         def GetParsePostCode(self):
0307                 return "\tif (bPythonIsHappy && !PyWinObject_AsTCHAR(ob%s, %s)) bPythonIsHappy = FALSE;\n" % (self.arg.name, self.GetIndirectedArgName(None, 2))
0308         def GetInterfaceArgCleanup(self):
0309                 return "\tPyWinObject_FreeTCHAR(%s);\n" % self.GetIndirectedArgName(None, 1)
0310         def GetBuildForInterfacePreCode(self):
0311                 # the variable was declared with just its builtin indirection
0312                 notdirected = self.GetIndirectedArgName(self.builtinIndirection, 1)
0313                 return "\tob%s = PyWinObject_FromTCHAR(%s);\n" % \
0314                            (self.arg.name, notdirected)
0315         def GetBuildForInterfacePostCode(self):
0316                 return "// ??? - TCHAR post code\n"
0317         def GetBuildForGatewayPostCode(self):
0318                 return "\tPy_XDECREF(ob%s);\n" % self.arg.name
0319 
0320 class ArgFormatterIID(ArgFormatterPythonCOM):
0321         def _GetPythonTypeDesc(self):
0322                 return "<o PyIID>"
0323         def GetParsePostCode(self):
0324                 return "\tif (!PyWinObject_AsIID(ob%s, &%s)) bPythonIsHappy = FALSE;\n" % (self.arg.name, self.arg.name)
0325         def GetBuildForInterfacePreCode(self):
0326 #         notdirected = self.GetIndirectedArgName(self.arg.indirectionLevel, 0)
0327                 notdirected = self.GetIndirectedArgName(None, 0)
0328                 return "\tob%s = PyWinObject_FromIID(%s);\n" % (self.arg.name, notdirected)
0329         def GetInterfaceCppObjectInfo(self):
0330                 return self.arg.name, "IID %s" % (self.arg.name)
0331 
0332 class ArgFormatterTime(ArgFormatterPythonCOM):
0333         def __init__(self, arg, builtinIndirection, declaredIndirection = 0):
0334                 # we don't want to declare LPSYSTEMTIME / LPFILETIME objects
0335                 if arg.indirectionLevel == 0 and arg.unc_type[:2] == "LP":
0336                         arg.unc_type = arg.unc_type[2:]
0337                         # reduce the builtin and increment the declaration
0338                         arg.indirectionLevel = arg.indirectionLevel + 1
0339                         builtinIndirection = 0
0340                 ArgFormatterPythonCOM.__init__(self, arg, builtinIndirection, declaredIndirection)
0341 
0342         def _GetPythonTypeDesc(self):
0343                 return "<o PyTime>"
0344         def GetParsePostCode(self):
0345                 # variable was declared with only the builtinIndirection
0346                 ### NOTE: this is an [in] ... so use only builtin
0347                 return '\tif (!PyTime_Check(ob%s)) {\n\t\tPyErr_SetString(PyExc_TypeError, "The argument must be a PyTime object");\n\t\tbPythonIsHappy = FALSE;\n\t}\n\tif (!((PyTime *)ob%s)->GetTime(%s)) bPythonIsHappy = FALSE;\n' % (self.arg.name, self.arg.name, self.GetIndirectedArgName(self.builtinIndirection, 1))
0348         def GetBuildForInterfacePreCode(self):
0349                 ### use just the builtinIndirection again...
0350                 notdirected = self.GetIndirectedArgName(self.builtinIndirection,0)
0351                 return "\tob%s = new PyTime(%s);\n" % (self.arg.name, notdirected)
0352         def GetBuildForInterfacePostCode(self):
0353                 ### hack to determine if we need to free stuff
0354                 ret = ''
0355                 if self.builtinIndirection + self.arg.indirectionLevel > 1:
0356                         # memory returned into an OLECHAR should be freed
0357                         ret = "\tCoTaskMemFree(%s);\n" % self.arg.name
0358                 return ret + ArgFormatterPythonCOM.GetBuildForInterfacePostCode(self)
0359 
0360 class ArgFormatterSTATSTG(ArgFormatterPythonCOM):
0361         def _GetPythonTypeDesc(self):
0362                 return "<o STATSTG>"
0363         def GetParsePostCode(self):
0364                 return '\tif (!PyCom_PyObjectAsSTATSTG(ob%s, %s, 0/*flags*/)) bPythonIsHappy = FALSE;\n' % (self.arg.name, self.GetIndirectedArgName(None, 1))
0365         def GetBuildForInterfacePreCode(self):
0366                 notdirected = self.GetIndirectedArgName(None, 1)
0367                 return "\tob%s = PyCom_PyObjectFromSTATSTG(%s);\n\t// STATSTG doco says our responsibility to free\n\tif ((%s).pwcsName) CoTaskMemFree((%s).pwcsName);\n" % (self.arg.name, self.GetIndirectedArgName(None, 1),notdirected,notdirected)
0368 
0369 class ArgFormatterGeneric(ArgFormatterPythonCOM):
0370         def _GetPythonTypeDesc(self):
0371                 return "<o %s>" % self.arg.type
0372         def GetParsePostCode(self):
0373                 return '\tif (!PyObject_As%s(ob%s, &%s) bPythonIsHappy = FALSE;\n' % (self.arg.type, self.arg.name, self.GetIndirectedArgName(None, 1))
0374         def GetInterfaceArgCleanup(self):
0375                 return '\tPyObject_Free%s(%s);\n' % (self.arg.type, self.arg.name)
0376         def GetBuildForInterfacePreCode(self):
0377                 notdirected = self.GetIndirectedArgName(None, 1)
0378                 return "\tob%s = PyObject_From%s(%s);\n" % (self.arg.name, self.arg.type, self.GetIndirectedArgName(None, 1))
0379 
0380 class ArgFormatterIDLIST(ArgFormatterPythonCOM):
0381         def _GetPythonTypeDesc(self):
0382                 return "<o PyIDL>"
0383         def GetParsePostCode(self):
0384                 return '\tif (bPythonIsHappy && !PyObject_AsPIDL(ob%s, &%s)) bPythonIsHappy = FALSE;\n' % (self.arg.name, self.GetIndirectedArgName(None, 1))
0385         def GetInterfaceArgCleanup(self):
0386                 return '\tPyObject_FreePIDL(%s);\n' % (self.arg.name,)
0387         def GetBuildForInterfacePreCode(self):
0388                 notdirected = self.GetIndirectedArgName(None, 1)
0389                 return "\tob%s = PyObject_FromPIDL(%s);\n" % (self.arg.name, self.GetIndirectedArgName(None, 1))
0390 
0391 class ArgFormatterHANDLE(ArgFormatterPythonCOM):
0392         def _GetPythonTypeDesc(self):
0393                 return "<o PyHANDLE>"
0394         def GetParsePostCode(self):
0395                 return '\tif (!PyWinObject_AsHANDLE(ob%s, &%s, FALSE) bPythonIsHappy = FALSE;\n' % (self.arg.name, self.GetIndirectedArgName(None, 1))
0396         def GetBuildForInterfacePreCode(self):
0397                 notdirected = self.GetIndirectedArgName(None, 1)
0398                 return "\tob%s = PyWinObject_FromHANDLE(%s);\n" % (self.arg.name, self.GetIndirectedArgName(None, 0))
0399 
0400 class ArgFormatterLARGE_INTEGER(ArgFormatterPythonCOM):
0401         def GetKeyName(self):
0402                 return "LARGE_INTEGER"
0403         def _GetPythonTypeDesc(self):
0404                 return "<o %s>" % self.GetKeyName()
0405         def GetParsePostCode(self):
0406                 return '\tif (!PyWinObject_As%s(ob%s, %s)) bPythonIsHappy = FALSE;\n' % (self.GetKeyName(), self.arg.name, self.GetIndirectedArgName(None, 1))
0407         def GetBuildForInterfacePreCode(self):
0408                 notdirected = self.GetIndirectedArgName(None, 0)
0409                 return "\tob%s = PyWinObject_From%s(%s);\n" % (self.arg.name, self.GetKeyName(), notdirected)
0410 
0411 class ArgFormatterULARGE_INTEGER(ArgFormatterLARGE_INTEGER):
0412         def GetKeyName(self):
0413                 return "ULARGE_INTEGER"
0414 
0415 class ArgFormatterInterface(ArgFormatterPythonCOM):
0416         def GetInterfaceCppObjectInfo(self):
0417                 return self.GetIndirectedArgName(1, self.arg.indirectionLevel), \
0418                            "%s * %s" % (self.GetUnconstType(), self.arg.name)
0419 
0420         def GetParsePostCode(self):
0421                 # This gets called for out params in gateway mode
0422                 if self.gatewayMode:
0423                         sArg = self.GetIndirectedArgName(None, 2)
0424                 else:
0425                 # vs. in params for interface mode.
0426                         sArg = self.GetIndirectedArgName(1, 2)
0427                 return "\tif (bPythonIsHappy && !PyCom_InterfaceFromPyInstanceOrObject(ob%s, IID_%s, (void **)%s, TRUE /* bNoneOK */))\n\t\t bPythonIsHappy = FALSE;\n" % (self.arg.name, self.arg.type, sArg)
0428         
0429         def GetBuildForInterfacePreCode(self):
0430                 return "\tob%s = PyCom_PyObjectFromIUnknown(%s, IID_%s, FALSE);\n" % (self.arg.name, self.arg.name, self.arg.type)
0431         
0432         def GetBuildForGatewayPreCode(self):
0433                 sPrefix = self._IndirectPrefix(self._GetDeclaredIndirection(), 1)
0434                 return "\tob%s = PyCom_PyObjectFromIUnknown(%s%s, IID_%s, TRUE);\n" % (self.arg.name, sPrefix, self.arg.name, self.arg.type)
0435 
0436         def GetInterfaceArgCleanup(self):
0437                 return "\tif (%s) %s->Release();\n" % (self.arg.name, self.arg.name)
0438 
0439 class ArgFormatterVARIANT(ArgFormatterPythonCOM):
0440         def GetParsePostCode(self):
0441                 return "\tif ( !PyCom_VariantFromPyObject(ob%s, %s) )\n\t\tbPythonIsHappy = FALSE;\n" % (self.arg.name, self.GetIndirectedArgName(None, 1))
0442 
0443         def GetBuildForGatewayPreCode(self):
0444                 notdirected = self.GetIndirectedArgName(None, 1)
0445                 return "\tob%s = PyCom_PyObjectFromVariant(%s);\n" % (self.arg.name, notdirected)
0446         def GetBuildForGatewayPostCode(self):
0447                 return "\tPy_XDECREF(ob%s);\n" % self.arg.name
0448 
0449                                           # Key :         , Python Type Description, ParseTuple format char
0450 ConvertSimpleTypes = {"BOOL":("BOOL", "int", "i"),
0451                                           "UINT":("UINT", "int", "i"),
0452                                           "BYTE": ("BYTE", "int", "i"),
0453                                           "INT": ("INT", "int", "i"),
0454                                           "DWORD": ("DWORD", "int", "l"),
0455                                           "HRESULT":("HRESULT", "int", "l"),
0456                                           "ULONG": ("ULONG", "int", "l"),
0457                                           "LONG": ("LONG", "int", "l"),
0458                                           "int": ("int", "int", "i"),
0459                                           "long": ("long", "int", "l"),
0460                                           "HWND": ("HWND", "HWND", "l"),
0461                                           "HDC": ("HDC", "HDC", "l"),
0462                                           "LPARAM" : ("LPARAM", "long", "l"),
0463                                           "LRESULT" : ("LRESULT", "long", "l"),
0464                                           "WPARAM" : ("LPARAM", "int", "i"),
0465                                           "DISPID": ("DISPID", "long", "l"),
0466                                           "APPBREAKFLAGS": ("int", "int", "i"),
0467                                           "BREAKRESUMEACTION": ("int", "int", "i"),
0468                                           "ERRORRESUMEACTION": ("int", "int", "i"),
0469                                           "BREAKREASON": ("int", "int", "i"),
0470                                           "BREAKPOINT_STATE": ("int", "int", "i"),
0471                                           "BREAKRESUME_ACTION": ("int", "int", "i"),
0472                                           "SOURCE_TEXT_ATTR": ("int", "int", "i"),
0473                                           "TEXT_DOC_ATTR": ("int", "int", "i"),
0474                                           "QUERYOPTION": ("int", "int", "i"),
0475                                           "PARSEACTION": ("int", "int", "i"),
0476 }
0477         
0478 class ArgFormatterSimple(ArgFormatter):
0479         """An arg formatter for simple integer etc types"""
0480         def GetFormatChar(self):
0481                 return ConvertSimpleTypes[self.arg.type][2]
0482         def _GetPythonTypeDesc(self):
0483                 return ConvertSimpleTypes[self.arg.type][1]
0484 
0485 AllConverters = {"const OLECHAR":        (ArgFormatterOLECHAR, 0, 1),
0486                                  "WCHAR":                        (ArgFormatterOLECHAR, 0, 1),
0487                                  "OLECHAR":                        (ArgFormatterOLECHAR, 0, 1),
0488                                  "LPCOLESTR":                (ArgFormatterOLECHAR, 1, 1),
0489                                  "LPOLESTR":                (ArgFormatterOLECHAR, 1, 1),
0490                                  "LPCWSTR":                        (ArgFormatterOLECHAR, 1, 1),
0491                                  "LPWSTR":                        (ArgFormatterOLECHAR, 1, 1),
0492                                  "LPCSTR":                        (ArgFormatterOLECHAR, 1, 1),
0493                                  "LPTSTR":                        (ArgFormatterTCHAR, 1, 1),
0494                                  "LPCTSTR":         (ArgFormatterTCHAR, 1, 1),
0495                                  "HANDLE":                        (ArgFormatterHANDLE, 0),
0496                                  "BSTR":                        (ArgFormatterBSTR, 1, 0),
0497                                  "const IID":                (ArgFormatterIID, 0),
0498                                  "CLSID":                        (ArgFormatterIID, 0),
0499                                  "IID":                                (ArgFormatterIID, 0),
0500                                  "GUID":                        (ArgFormatterIID, 0),
0501                                  "const GUID":                (ArgFormatterIID, 0),
0502                                  "const IID":                (ArgFormatterIID, 0),
0503                                  "REFCLSID":                (ArgFormatterIID, 0),
0504                                  "REFIID":                        (ArgFormatterIID, 0),
0505                                  "REFGUID":                        (ArgFormatterIID, 0),
0506                                  "const FILETIME":        (ArgFormatterTime, 0),
0507                                  "const SYSTEMTIME":(ArgFormatterTime, 0),
0508                                  "const LPSYSTEMTIME":(ArgFormatterTime, 1, 1),
0509                                  "LPSYSTEMTIME":        (ArgFormatterTime, 1, 1),
0510                                  "FILETIME":                (ArgFormatterTime, 0),
0511                                  "SYSTEMTIME":                (ArgFormatterTime, 0),
0512                                  "STATSTG":                        (ArgFormatterSTATSTG, 0),
0513                                  "LARGE_INTEGER":        (ArgFormatterLARGE_INTEGER, 0),
0514                                  "ULARGE_INTEGER":        (ArgFormatterULARGE_INTEGER, 0),
0515                                  "VARIANT":                        (ArgFormatterVARIANT, 0),
0516                                  "float":                        (ArgFormatterFloat, 0),
0517                                  "single":                        (ArgFormatterFloat, 0),
0518                                  "short":                        (ArgFormatterShort, 0),
0519                                  "WORD":                        (ArgFormatterShort, 0),
0520                                  "VARIANT_BOOL":        (ArgFormatterShort, 0),
0521                                  "HWND":                        (ArgFormatterShort, 0),
0522                                  "HMENU":                        (ArgFormatterShort, 0),
0523                                  "HOLEMENU":                        (ArgFormatterShort, 0),
0524                                  "HICON":                        (ArgFormatterShort, 0),
0525                                  "UINT":                        (ArgFormatterShort, 0),
0526                                  "SVSIF":                        (ArgFormatterShort, 0),
0527                                  "Control":                        (ArgFormatterInterface, 0, 1),
0528                                  "DataObject":                (ArgFormatterInterface, 0, 1),
0529                                  "_PropertyBag":        (ArgFormatterInterface, 0, 1),
0530                                  "AsyncProp":                (ArgFormatterInterface, 0, 1),
0531                                  "DataSource":                (ArgFormatterInterface, 0, 1),
0532                                  "DataFormat":                (ArgFormatterInterface, 0, 1),
0533                                  "void **":                        (ArgFormatterInterface, 2, 2),
0534                                  "ITEMIDLIST":                (ArgFormatterIDLIST, 0, 0),
0535                                  "LPITEMIDLIST":                (ArgFormatterIDLIST, 0, 1),
0536                                  "LPCITEMIDLIST":                (ArgFormatterIDLIST, 0, 1),
0537                                  "const ITEMIDLIST":                (ArgFormatterIDLIST, 0, 1),
0538 }
0539 
0540 # Auto-add all the simple types
0541 for key in ConvertSimpleTypes.keys():
0542         AllConverters[key] = ArgFormatterSimple, 0
0543 
0544 def make_arg_converter(arg):
0545         try:
0546                 clz = AllConverters[arg.type][0]
0547                 bin = AllConverters[arg.type][1]
0548                 decl = 0
0549                 if len(AllConverters[arg.type])>2:
0550                         decl = AllConverters[arg.type][2]
0551                 return clz(arg,bin, decl)
0552         except KeyError:
0553                 if arg.type[0]=="I":
0554                         return ArgFormatterInterface(arg, 0, 1)
0555 
0556                 raise error_not_supported, "The type '%s' (%s) is unknown." % (arg.type, arg.name)
0557 
0558                 
0559 #############################################################
0560 #
0561 # The instances that represent the args, methods and interface
0562 class Argument:
0563         """A representation of an argument to a COM method
0564         
0565         This class contains information about a specific argument to a method.
0566         In addition, methods exist so that an argument knows how to convert itself
0567         to/from Python arguments.
0568         """
0569 #                                                                   in,out                                          type                    name                   [      ]
0570 #                                                            --------------                               --------          ------------          ------
0571         regex = regex.compile('/\\* \\[\\([^\\]]*.*\\)] \\*/[ \t]\\(.*[\\* ]\\)\\([a-zA-Z0-9]+\\)\\(\\[ *]\\)?[),]')
0572         def __init__(self, good_interface_names):
0573                 self.good_interface_names = good_interface_names
0574                 self.inout = self.name = self.type = None
0575                 self.const = 0
0576                 self.arrayDecl = 0
0577         def BuildFromFile(self, file):
0578                 """Parse and build my data from a file
0579                 
0580                 Reads the next line in the file, and matches it as an argument
0581                 description.  If not a valid argument line, an error_not_found exception
0582                 is raised.
0583                 """
0584                 line = file.readline()
0585                 if self.regex.search(line)<0:
0586                         raise error_not_found
0587                 self.name = self.regex.group(3)
0588                 self.inout = string.split(self.regex.group(1),'][')
0589                 typ = string.strip(self.regex.group(2))
0590                 self.raw_type = typ
0591                 self.indirectionLevel = 0
0592                 if self.regex.group(4): # Has "[ ]" decl
0593                         self.arrayDecl = 1
0594                         try:
0595                                 pos = string.rindex(typ, "__RPC_FAR")
0596                                 self.indirectionLevel = self.indirectionLevel + 1
0597                                 typ = string.strip(typ[:pos])
0598                         except ValueError:
0599                                 pass
0600                 
0601                 while 1:
0602                         try:
0603                                 pos = string.rindex(typ, "__RPC_FAR *")
0604                                 self.indirectionLevel = self.indirectionLevel + 1
0605                                 typ = string.strip(typ[:pos])
0606                         except ValueError:
0607                                 break
0608                 self.type = typ
0609                 if self.type[:6]=="const ":
0610                         self.unc_type = self.type[6:]
0611                 else:
0612                         self.unc_type = self.type
0613                 
0614                 if VERBOSE:
0615                         print "    Arg %s of type %s%s (%s)" % (self.name, self.type, "*" * self.indirectionLevel, self.inout)
0616 
0617         def HasAttribute(self, typ):
0618                 """Determines if the argument has the specific attribute.
0619                 
0620                 Argument attributes are specified in the header file, such as
0621                 "[in][out][retval]" etc.  You can pass a specific string (eg "out")
0622                 to find if this attribute was specified for the argument
0623                 """
0624                 return typ in self.inout
0625 
0626         def GetRawDeclaration(self):
0627                 ret = "%s %s" % (self.raw_type, self.name)
0628                 if self.arrayDecl:
0629                         ret = ret + "[]"
0630                 return ret
0631 
0632 class Method:
0633         """A representation of a C++ method on a COM interface
0634         
0635         This class contains information about a specific method, as well as 
0636         a list of all @Argument@s
0637         """
0638 #                                                                          options         ret type callconv       name
0639 #                                                            ----------------- -------- -------- --------
0640         regex = regex.compile('virtual \\(/\\*.*\\*/ \\)?\\(.*\\) \\(.*\\) \\(.*\\)(\w?')
0641         def __init__(self, good_interface_names ):
0642                 self.good_interface_names = good_interface_names
0643                 self.name = self.result = self.callconv = None
0644                 self.args = []
0645         def BuildFromFile(self, file):
0646                 """Parse and build my data from a file
0647                 
0648                 Reads the next line in the file, and matches it as a method
0649                 description.  If not a valid method line, an error_not_found exception
0650                 is raised.
0651                 """
0652                 str = file.readline()
0653                 if self.regex.search(str, 0) == -1:
0654                         raise error_not_found
0655                 self.name = self.regex.group(4)
0656                 self.result = self.regex.group(2)
0657                 if self.result != "HRESULT":
0658                         if self.result=="DWORD": # DWORD is for old old stuff?
0659                                 print "Warning: Old style interface detected - compilation errors likely!"
0660                         else:
0661                                 print "Method %s - Only HRESULT return types are supported." % self.name
0662 #                         raise error_not_supported,              if VERBOSE:
0663                         print "  Method %s %s(" % (self.result, self.name)
0664                 while 1:
0665                         arg = Argument(self.good_interface_names)
0666                         try:
0667                                 arg.BuildFromFile(file)
0668                                 self.args.append(arg)
0669                         except error_not_found:
0670                                 break
0671 
0672 class Interface:
0673         """A representation of a C++ COM Interface
0674         
0675         This class contains information about a specific interface, as well as 
0676         a list of all @Method@s
0677         """
0678 #                                                                   name                           base
0679 #                                                                  --------                  --------
0680         regex = regex.compile("\\(interface\\|\\) \\([^ ]*\\) : public \\(.*\\)$")
0681         def __init__(self):
0682                 self.methods = []
0683                 self.name = self.regex.group(2)
0684                 self.base = self.regex.group(3)
0685                 if VERBOSE:
0686                         print "Interface %s : public %s" % (self.name, self.base)
0687 
0688         def BuildMethods(self, file):
0689                 """Build all sub-methods for this interface"""
0690                 # skip the next 2 lines.
0691                 file.readline();file.readline();
0692                 while 1:
0693                         try:
0694                                 method = Method([self.name])
0695                                 method.BuildFromFile(file)
0696                                 self.methods.append(method)
0697                         except error_not_found:
0698                                 break
0699         
0700 def find_interface(interfaceName, file):
0701         """Find and return an interface in a file
0702         
0703         Given an interface name and file, search for the specified interface.
0704         
0705         Upon return, the interface itself has been built, 
0706         but not the methods.
0707         """
0708 
0709         line = file.readline()
0710         while line:
0711                 if Interface.regex.search(line, 0) >=0:
0712                         name = Interface.regex.group(2)
0713                         print name
0714                         if name==interfaceName:
0715                                 return Interface()
0716                 line = file.readline()
0717         raise error_not_found
0718 
0719         
0720 def parse_interface_info(interfaceName, file):
0721         """Find, parse and return an interface in a file
0722         
0723         Given an interface name and file, search for the specified interface.
0724         
0725         Upon return, the interface itself is fully built,
0726         """
0727         try:
0728                 interface = find_interface(interfaceName, file)
0729                 interface.BuildMethods(file)
0730                 return interface
0731         except regex.error:
0732                 traceback.print_exc()
0733                 print "The interface could not be built, as the regular expression failed!"
0734 def test():
0735         f=open("d:\\msdev\\include\\objidl.h")
0736         try:
0737                 parse_interface_info("IPersistStream", f)
0738         finally:
0739                 f.close()
0740 
0741 def test_regex(r,text):
0742         res=r.search(text,0)
0743         if res==-1:
0744                 print "** Not found"
0745         else:
0746                 print "%d\n%s\n%s\n%s\n%s" % (res, r.group(1), r.group(2), r.group(3), r.group(4))
0747 
0748 

Generated by PyXR 0.9.4
SourceForge.net Logo