0001 """Utility file for generating PyIEnum support. 0002 0003 This is almost a 'template' file. It simplay contains almost full 0004 C++ source code for PyIEnum* support, and the Python code simply 0005 substitutes the appropriate interface name. 0006 0007 This module is notmally not used directly - the @makegw@ module 0008 automatically calls this. 0009 """ 0010 # 0011 # INTERNAL FUNCTIONS 0012 # 0013 # 0014 import string 0015 0016 def is_interface_enum(enumtype): 0017 return not (enumtype[0] in string.uppercase and enumtype[2] in string.uppercase) 0018 0019 0020 def _write_enumifc_cpp(f, interface): 0021 enumtype = interface.name[5:] 0022 if is_interface_enum(enumtype): 0023 # Assume an interface. 0024 enum_interface = "I" + enumtype[:-1] 0025 converter = "PyObject *ob = PyCom_PyObjectFromIUnknown(rgVar[i], IID_%(enum_interface)s, FALSE);" % locals() 0026 arraydeclare = "%(enum_interface)s **rgVar = new %(enum_interface)s *[celt];" % locals() 0027 else: 0028 # Enum of a simple structure 0029 converter = "PyObject *ob = PyCom_PyObjectFrom%(enumtype)s(&rgVar[i]);" % locals() 0030 arraydeclare = "%(enumtype)s *rgVar = new %(enumtype)s[celt];" % locals() 0031 0032 f.write(\ 0033 ''' 0034 // --------------------------------------------------- 0035 // 0036 // Interface Implementation 0037 0038 PyIEnum%(enumtype)s::PyIEnum%(enumtype)s(IUnknown *pdisp): 0039 PyIUnknown(pdisp) 0040 { 0041 ob_type = &type; 0042 } 0043 0044 PyIEnum%(enumtype)s::~PyIEnum%(enumtype)s() 0045 { 0046 } 0047 0048 /* static */ IEnum%(enumtype)s *PyIEnum%(enumtype)s::GetI(PyObject *self) 0049 { 0050 return (IEnum%(enumtype)s *)PyIUnknown::GetI(self); 0051 } 0052 0053 // @pymethod object|PyIEnum%(enumtype)s|Next|Retrieves a specified number of items in the enumeration sequence. 0054 PyObject *PyIEnum%(enumtype)s::Next(PyObject *self, PyObject *args) 0055 { 0056 long celt = 1; 0057 // @pyparm int|num|1|Number of items to retrieve. 0058 if ( !PyArg_ParseTuple(args, "|l:Next", &celt) ) 0059 return NULL; 0060 0061 IEnum%(enumtype)s *pIE%(enumtype)s = GetI(self); 0062 if ( pIE%(enumtype)s == NULL ) 0063 return NULL; 0064 0065 %(arraydeclare)s 0066 if ( rgVar == NULL ) { 0067 PyErr_SetString(PyExc_MemoryError, "allocating result %(enumtype)ss"); 0068 return NULL; 0069 } 0070 0071 int i; 0072 /* for ( i = celt; i--; ) 0073 // *** possibly init each structure element??? 0074 */ 0075 0076 ULONG celtFetched = 0; 0077 PY_INTERFACE_PRECALL; 0078 HRESULT hr = pIE%(enumtype)s->Next(celt, rgVar, &celtFetched); 0079 PY_INTERFACE_POSTCALL; 0080 if ( HRESULT_CODE(hr) != ERROR_NO_MORE_ITEMS && FAILED(hr) ) 0081 { 0082 delete [] rgVar; 0083 return PyCom_BuildPyException(hr,pIE%(enumtype)s, IID_IE%(enumtype)s); 0084 } 0085 0086 PyObject *result = PyTuple_New(celtFetched); 0087 if ( result != NULL ) 0088 { 0089 for ( i = celtFetched; i--; ) 0090 { 0091 %(converter)s 0092 if ( ob == NULL ) 0093 { 0094 Py_DECREF(result); 0095 result = NULL; 0096 break; 0097 } 0098 PyTuple_SET_ITEM(result, i, ob); 0099 } 0100 } 0101 0102 /* for ( i = celtFetched; i--; ) 0103 // *** possibly cleanup each structure element??? 0104 */ 0105 delete [] rgVar; 0106 return result; 0107 } 0108 0109 // @pymethod |PyIEnum%(enumtype)s|Skip|Skips over the next specified elementes. 0110 PyObject *PyIEnum%(enumtype)s::Skip(PyObject *self, PyObject *args) 0111 { 0112 long celt; 0113 if ( !PyArg_ParseTuple(args, "l:Skip", &celt) ) 0114 return NULL; 0115 0116 IEnum%(enumtype)s *pIE%(enumtype)s = GetI(self); 0117 if ( pIE%(enumtype)s == NULL ) 0118 return NULL; 0119 0120 PY_INTERFACE_PRECALL; 0121 HRESULT hr = pIE%(enumtype)s->Skip(celt); 0122 PY_INTERFACE_POSTCALL; 0123 if ( FAILED(hr) ) 0124 return PyCom_BuildPyException(hr, pIE%(enumtype)s, IID_IE%(enumtype)s); 0125 0126 Py_INCREF(Py_None); 0127 return Py_None; 0128 } 0129 0130 // @pymethod |PyIEnum%(enumtype)s|Reset|Resets the enumeration sequence to the beginning. 0131 PyObject *PyIEnum%(enumtype)s::Reset(PyObject *self, PyObject *args) 0132 { 0133 if ( !PyArg_ParseTuple(args, ":Reset") ) 0134 return NULL; 0135 0136 IEnum%(enumtype)s *pIE%(enumtype)s = GetI(self); 0137 if ( pIE%(enumtype)s == NULL ) 0138 return NULL; 0139 0140 PY_INTERFACE_PRECALL; 0141 HRESULT hr = pIE%(enumtype)s->Reset(); 0142 PY_INTERFACE_POSTCALL; 0143 if ( FAILED(hr) ) 0144 return PyCom_BuildPyException(hr, pIE%(enumtype)s, IID_IE%(enumtype)s); 0145 0146 Py_INCREF(Py_None); 0147 return Py_None; 0148 } 0149 0150 // @pymethod <o PyIEnum%(enumtype)s>|PyIEnum%(enumtype)s|Clone|Creates another enumerator that contains the same enumeration state as the current one 0151 PyObject *PyIEnum%(enumtype)s::Clone(PyObject *self, PyObject *args) 0152 { 0153 if ( !PyArg_ParseTuple(args, ":Clone") ) 0154 return NULL; 0155 0156 IEnum%(enumtype)s *pIE%(enumtype)s = GetI(self); 0157 if ( pIE%(enumtype)s == NULL ) 0158 return NULL; 0159 0160 IEnum%(enumtype)s *pClone; 0161 PY_INTERFACE_PRECALL; 0162 HRESULT hr = pIE%(enumtype)s->Clone(&pClone); 0163 PY_INTERFACE_POSTCALL; 0164 if ( FAILED(hr) ) 0165 return PyCom_BuildPyException(hr, pIE%(enumtype)s, IID_IE%(enumtype)s); 0166 0167 return PyCom_PyObjectFromIUnknown(pClone, IID_IEnum%(enumtype)s, FALSE); 0168 } 0169 0170 // @object PyIEnum%(enumtype)s|A Python interface to IEnum%(enumtype)s 0171 static struct PyMethodDef PyIEnum%(enumtype)s_methods[] = 0172 { 0173 { "Next", PyIEnum%(enumtype)s::Next, 1 }, // @pymeth Next|Retrieves a specified number of items in the enumeration sequence. 0174 { "Skip", PyIEnum%(enumtype)s::Skip, 1 }, // @pymeth Skip|Skips over the next specified elementes. 0175 { "Reset", PyIEnum%(enumtype)s::Reset, 1 }, // @pymeth Reset|Resets the enumeration sequence to the beginning. 0176 { "Clone", PyIEnum%(enumtype)s::Clone, 1 }, // @pymeth Clone|Creates another enumerator that contains the same enumeration state as the current one. 0177 { NULL } 0178 }; 0179 0180 PyComTypeObject PyIEnum%(enumtype)s::type("PyIEnum%(enumtype)s", 0181 &PyIUnknown::type, 0182 sizeof(PyIEnum%(enumtype)s), 0183 PyIEnum%(enumtype)s_methods, 0184 GET_PYCOM_CTOR(PyIEnum%(enumtype)s)); 0185 ''' % locals() ) 0186 0187 0188 0189 def _write_enumgw_cpp(f, interface): 0190 enumtype = interface.name[5:] 0191 if is_interface_enum(enumtype): 0192 # Assume an interface. 0193 enum_interface = "I" + enumtype[:-1] 0194 converter = "if ( !PyCom_InterfaceFromPyObject(ob, IID_%(enum_interface)s, (void **)&rgVar[i], FALSE) )" % locals() 0195 argdeclare="%(enum_interface)s __RPC_FAR * __RPC_FAR *rgVar" % locals() 0196 else: 0197 argdeclare="%(enumtype)s __RPC_FAR *rgVar" % locals() 0198 converter="if ( !PyCom_PyObjectAs%(enumtype)s(ob, &rgVar[i]) )" % locals() 0199 f.write( 0200 ''' 0201 // --------------------------------------------------- 0202 // 0203 // Gateway Implementation 0204 0205 // Std delegation 0206 STDMETHODIMP_(ULONG) PyGEnum%(enumtype)s::AddRef(void) {return PyGatewayBase::AddRef();} 0207 STDMETHODIMP_(ULONG) PyGEnum%(enumtype)s::Release(void) {return PyGatewayBase::Release();} 0208 STDMETHODIMP PyGEnum%(enumtype)s::QueryInterface(REFIID iid, void ** obj) {return PyGatewayBase::QueryInterface(iid, obj);} 0209 STDMETHODIMP PyGEnum%(enumtype)s::GetTypeInfoCount(UINT FAR* pctInfo) {return PyGatewayBase::GetTypeInfoCount(pctInfo);} 0210 STDMETHODIMP PyGEnum%(enumtype)s::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptInfo) {return PyGatewayBase::GetTypeInfo(itinfo, lcid, pptInfo);} 0211 STDMETHODIMP PyGEnum%(enumtype)s::GetIDsOfNames(REFIID refiid, OLECHAR FAR* FAR* rgszNames, UINT cNames, LCID lcid, DISPID FAR* rgdispid) {return PyGatewayBase::GetIDsOfNames( refiid, rgszNames, cNames, lcid, rgdispid);} 0212 STDMETHODIMP PyGEnum%(enumtype)s::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* params, VARIANT FAR* pVarResult, EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr) {return PyGatewayBase::Invoke( dispid, riid, lcid, wFlags, params, pVarResult, pexcepinfo, puArgErr);} 0213 0214 STDMETHODIMP PyGEnum%(enumtype)s::Next( 0215 /* [in] */ ULONG celt, 0216 /* [length_is][size_is][out] */ %(argdeclare)s, 0217 /* [out] */ ULONG __RPC_FAR *pCeltFetched) 0218 { 0219 PY_GATEWAY_METHOD; 0220 PyObject *result; 0221 HRESULT hr = InvokeViaPolicy("Next", &result, "i", celt); 0222 if ( FAILED(hr) ) 0223 return hr; 0224 0225 if ( !PySequence_Check(result) ) 0226 goto error; 0227 int len; 0228 len = PyObject_Length(result); 0229 if ( len == -1 ) 0230 goto error; 0231 if ( len > (int)celt) 0232 len = celt; 0233 0234 if ( pCeltFetched ) 0235 *pCeltFetched = len; 0236 0237 int i; 0238 for ( i = 0; i < len; ++i ) 0239 { 0240 PyObject *ob = PySequence_GetItem(result, i); 0241 if ( ob == NULL ) 0242 goto error; 0243 0244 %(converter)s 0245 { 0246 Py_DECREF(result); 0247 return PyCom_SetCOMErrorFromPyException(IID_IEnum%(enumtype)s); 0248 } 0249 } 0250 0251 Py_DECREF(result); 0252 0253 return len < (int)celt ? S_FALSE : S_OK; 0254 0255 error: 0256 PyErr_Clear(); // just in case 0257 Py_DECREF(result); 0258 return PyCom_SetCOMErrorFromSimple(E_FAIL, IID_IEnum%(enumtype)s, "Next() did not return a sequence of objects"); 0259 } 0260 0261 STDMETHODIMP PyGEnum%(enumtype)s::Skip( 0262 /* [in] */ ULONG celt) 0263 { 0264 PY_GATEWAY_METHOD; 0265 return InvokeViaPolicy("Skip", NULL, "i", celt); 0266 } 0267 0268 STDMETHODIMP PyGEnum%(enumtype)s::Reset(void) 0269 { 0270 PY_GATEWAY_METHOD; 0271 return InvokeViaPolicy("Reset"); 0272 } 0273 0274 STDMETHODIMP PyGEnum%(enumtype)s::Clone( 0275 /* [out] */ IEnum%(enumtype)s __RPC_FAR *__RPC_FAR *ppEnum) 0276 { 0277 PY_GATEWAY_METHOD; 0278 PyObject * result; 0279 HRESULT hr = InvokeViaPolicy("Clone", &result); 0280 if ( FAILED(hr) ) 0281 return hr; 0282 0283 /* 0284 ** Make sure we have the right kind of object: we should have some kind 0285 ** of IUnknown subclass wrapped into a PyIUnknown instance. 0286 */ 0287 if ( !PyIBase::is_object(result, &PyIUnknown::type) ) 0288 { 0289 /* the wrong kind of object was returned to us */ 0290 Py_DECREF(result); 0291 return PyCom_SetCOMErrorFromSimple(E_FAIL, IID_IEnum%(enumtype)s); 0292 } 0293 0294 /* 0295 ** Get the IUnknown out of the thing. note that the Python ob maintains 0296 ** a reference, so we don't have to explicitly AddRef() here. 0297 */ 0298 IUnknown *punk = ((PyIUnknown *)result)->m_obj; 0299 if ( !punk ) 0300 { 0301 /* damn. the object was released. */ 0302 Py_DECREF(result); 0303 return PyCom_SetCOMErrorFromSimple(E_FAIL, IID_IEnum%(enumtype)s); 0304 } 0305 0306 /* 0307 ** Get the interface we want. note it is returned with a refcount. 0308 ** This QI is actually going to instantiate a PyGEnum%(enumtype)s. 0309 */ 0310 hr = punk->QueryInterface(IID_IEnum%(enumtype)s, (LPVOID *)ppEnum); 0311 0312 /* done with the result; this DECREF is also for <punk> */ 0313 Py_DECREF(result); 0314 0315 return PyCom_SetCOMErrorFromSimple(hr, IID_IEnum%(enumtype)s, "Python could not convert the result from Next() into the required COM interface"); 0316 } 0317 ''' % locals()) 0318
Generated by PyXR 0.9.4