Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

makegwenum.py 9.6KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. """Utility file for generating PyIEnum support.
  2. This is almost a 'template' file. It simplay contains almost full
  3. C++ source code for PyIEnum* support, and the Python code simply
  4. substitutes the appropriate interface name.
  5. This module is notmally not used directly - the @makegw@ module
  6. automatically calls this.
  7. """
  8. #
  9. # INTERNAL FUNCTIONS
  10. #
  11. #
  12. import string
  13. def is_interface_enum(enumtype):
  14. return not (enumtype[0] in string.uppercase and enumtype[2] in string.uppercase)
  15. def _write_enumifc_cpp(f, interface):
  16. enumtype = interface.name[5:]
  17. if is_interface_enum(enumtype):
  18. # Assume an interface.
  19. enum_interface = "I" + enumtype[:-1]
  20. converter = (
  21. "PyObject *ob = PyCom_PyObjectFromIUnknown(rgVar[i], IID_%(enum_interface)s, FALSE);"
  22. % locals()
  23. )
  24. arraydeclare = (
  25. "%(enum_interface)s **rgVar = new %(enum_interface)s *[celt];" % locals()
  26. )
  27. else:
  28. # Enum of a simple structure
  29. converter = (
  30. "PyObject *ob = PyCom_PyObjectFrom%(enumtype)s(&rgVar[i]);" % locals()
  31. )
  32. arraydeclare = "%(enumtype)s *rgVar = new %(enumtype)s[celt];" % locals()
  33. f.write(
  34. """
  35. // ---------------------------------------------------
  36. //
  37. // Interface Implementation
  38. PyIEnum%(enumtype)s::PyIEnum%(enumtype)s(IUnknown *pdisp):
  39. PyIUnknown(pdisp)
  40. {
  41. ob_type = &type;
  42. }
  43. PyIEnum%(enumtype)s::~PyIEnum%(enumtype)s()
  44. {
  45. }
  46. /* static */ IEnum%(enumtype)s *PyIEnum%(enumtype)s::GetI(PyObject *self)
  47. {
  48. return (IEnum%(enumtype)s *)PyIUnknown::GetI(self);
  49. }
  50. // @pymethod object|PyIEnum%(enumtype)s|Next|Retrieves a specified number of items in the enumeration sequence.
  51. PyObject *PyIEnum%(enumtype)s::Next(PyObject *self, PyObject *args)
  52. {
  53. long celt = 1;
  54. // @pyparm int|num|1|Number of items to retrieve.
  55. if ( !PyArg_ParseTuple(args, "|l:Next", &celt) )
  56. return NULL;
  57. IEnum%(enumtype)s *pIE%(enumtype)s = GetI(self);
  58. if ( pIE%(enumtype)s == NULL )
  59. return NULL;
  60. %(arraydeclare)s
  61. if ( rgVar == NULL ) {
  62. PyErr_SetString(PyExc_MemoryError, "allocating result %(enumtype)ss");
  63. return NULL;
  64. }
  65. int i;
  66. /* for ( i = celt; i--; )
  67. // *** possibly init each structure element???
  68. */
  69. ULONG celtFetched = 0;
  70. PY_INTERFACE_PRECALL;
  71. HRESULT hr = pIE%(enumtype)s->Next(celt, rgVar, &celtFetched);
  72. PY_INTERFACE_POSTCALL;
  73. if ( HRESULT_CODE(hr) != ERROR_NO_MORE_ITEMS && FAILED(hr) )
  74. {
  75. delete [] rgVar;
  76. return PyCom_BuildPyException(hr,pIE%(enumtype)s, IID_IE%(enumtype)s);
  77. }
  78. PyObject *result = PyTuple_New(celtFetched);
  79. if ( result != NULL )
  80. {
  81. for ( i = celtFetched; i--; )
  82. {
  83. %(converter)s
  84. if ( ob == NULL )
  85. {
  86. Py_DECREF(result);
  87. result = NULL;
  88. break;
  89. }
  90. PyTuple_SET_ITEM(result, i, ob);
  91. }
  92. }
  93. /* for ( i = celtFetched; i--; )
  94. // *** possibly cleanup each structure element???
  95. */
  96. delete [] rgVar;
  97. return result;
  98. }
  99. // @pymethod |PyIEnum%(enumtype)s|Skip|Skips over the next specified elementes.
  100. PyObject *PyIEnum%(enumtype)s::Skip(PyObject *self, PyObject *args)
  101. {
  102. long celt;
  103. if ( !PyArg_ParseTuple(args, "l:Skip", &celt) )
  104. return NULL;
  105. IEnum%(enumtype)s *pIE%(enumtype)s = GetI(self);
  106. if ( pIE%(enumtype)s == NULL )
  107. return NULL;
  108. PY_INTERFACE_PRECALL;
  109. HRESULT hr = pIE%(enumtype)s->Skip(celt);
  110. PY_INTERFACE_POSTCALL;
  111. if ( FAILED(hr) )
  112. return PyCom_BuildPyException(hr, pIE%(enumtype)s, IID_IE%(enumtype)s);
  113. Py_INCREF(Py_None);
  114. return Py_None;
  115. }
  116. // @pymethod |PyIEnum%(enumtype)s|Reset|Resets the enumeration sequence to the beginning.
  117. PyObject *PyIEnum%(enumtype)s::Reset(PyObject *self, PyObject *args)
  118. {
  119. if ( !PyArg_ParseTuple(args, ":Reset") )
  120. return NULL;
  121. IEnum%(enumtype)s *pIE%(enumtype)s = GetI(self);
  122. if ( pIE%(enumtype)s == NULL )
  123. return NULL;
  124. PY_INTERFACE_PRECALL;
  125. HRESULT hr = pIE%(enumtype)s->Reset();
  126. PY_INTERFACE_POSTCALL;
  127. if ( FAILED(hr) )
  128. return PyCom_BuildPyException(hr, pIE%(enumtype)s, IID_IE%(enumtype)s);
  129. Py_INCREF(Py_None);
  130. return Py_None;
  131. }
  132. // @pymethod <o PyIEnum%(enumtype)s>|PyIEnum%(enumtype)s|Clone|Creates another enumerator that contains the same enumeration state as the current one
  133. PyObject *PyIEnum%(enumtype)s::Clone(PyObject *self, PyObject *args)
  134. {
  135. if ( !PyArg_ParseTuple(args, ":Clone") )
  136. return NULL;
  137. IEnum%(enumtype)s *pIE%(enumtype)s = GetI(self);
  138. if ( pIE%(enumtype)s == NULL )
  139. return NULL;
  140. IEnum%(enumtype)s *pClone;
  141. PY_INTERFACE_PRECALL;
  142. HRESULT hr = pIE%(enumtype)s->Clone(&pClone);
  143. PY_INTERFACE_POSTCALL;
  144. if ( FAILED(hr) )
  145. return PyCom_BuildPyException(hr, pIE%(enumtype)s, IID_IE%(enumtype)s);
  146. return PyCom_PyObjectFromIUnknown(pClone, IID_IEnum%(enumtype)s, FALSE);
  147. }
  148. // @object PyIEnum%(enumtype)s|A Python interface to IEnum%(enumtype)s
  149. static struct PyMethodDef PyIEnum%(enumtype)s_methods[] =
  150. {
  151. { "Next", PyIEnum%(enumtype)s::Next, 1 }, // @pymeth Next|Retrieves a specified number of items in the enumeration sequence.
  152. { "Skip", PyIEnum%(enumtype)s::Skip, 1 }, // @pymeth Skip|Skips over the next specified elementes.
  153. { "Reset", PyIEnum%(enumtype)s::Reset, 1 }, // @pymeth Reset|Resets the enumeration sequence to the beginning.
  154. { "Clone", PyIEnum%(enumtype)s::Clone, 1 }, // @pymeth Clone|Creates another enumerator that contains the same enumeration state as the current one.
  155. { NULL }
  156. };
  157. PyComEnumTypeObject PyIEnum%(enumtype)s::type("PyIEnum%(enumtype)s",
  158. &PyIUnknown::type,
  159. sizeof(PyIEnum%(enumtype)s),
  160. PyIEnum%(enumtype)s_methods,
  161. GET_PYCOM_CTOR(PyIEnum%(enumtype)s));
  162. """
  163. % locals()
  164. )
  165. def _write_enumgw_cpp(f, interface):
  166. enumtype = interface.name[5:]
  167. if is_interface_enum(enumtype):
  168. # Assume an interface.
  169. enum_interface = "I" + enumtype[:-1]
  170. converter = (
  171. "if ( !PyCom_InterfaceFromPyObject(ob, IID_%(enum_interface)s, (void **)&rgVar[i], FALSE) )"
  172. % locals()
  173. )
  174. argdeclare = "%(enum_interface)s __RPC_FAR * __RPC_FAR *rgVar" % locals()
  175. else:
  176. argdeclare = "%(enumtype)s __RPC_FAR *rgVar" % locals()
  177. converter = "if ( !PyCom_PyObjectAs%(enumtype)s(ob, &rgVar[i]) )" % locals()
  178. f.write(
  179. """
  180. // ---------------------------------------------------
  181. //
  182. // Gateway Implementation
  183. // Std delegation
  184. STDMETHODIMP_(ULONG) PyGEnum%(enumtype)s::AddRef(void) {return PyGatewayBase::AddRef();}
  185. STDMETHODIMP_(ULONG) PyGEnum%(enumtype)s::Release(void) {return PyGatewayBase::Release();}
  186. STDMETHODIMP PyGEnum%(enumtype)s::QueryInterface(REFIID iid, void ** obj) {return PyGatewayBase::QueryInterface(iid, obj);}
  187. STDMETHODIMP PyGEnum%(enumtype)s::GetTypeInfoCount(UINT FAR* pctInfo) {return PyGatewayBase::GetTypeInfoCount(pctInfo);}
  188. STDMETHODIMP PyGEnum%(enumtype)s::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptInfo) {return PyGatewayBase::GetTypeInfo(itinfo, lcid, pptInfo);}
  189. 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);}
  190. 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);}
  191. STDMETHODIMP PyGEnum%(enumtype)s::Next(
  192. /* [in] */ ULONG celt,
  193. /* [length_is][size_is][out] */ %(argdeclare)s,
  194. /* [out] */ ULONG __RPC_FAR *pCeltFetched)
  195. {
  196. PY_GATEWAY_METHOD;
  197. PyObject *result;
  198. HRESULT hr = InvokeViaPolicy("Next", &result, "i", celt);
  199. if ( FAILED(hr) )
  200. return hr;
  201. if ( !PySequence_Check(result) )
  202. goto error;
  203. int len;
  204. len = PyObject_Length(result);
  205. if ( len == -1 )
  206. goto error;
  207. if ( len > (int)celt)
  208. len = celt;
  209. if ( pCeltFetched )
  210. *pCeltFetched = len;
  211. int i;
  212. for ( i = 0; i < len; ++i )
  213. {
  214. PyObject *ob = PySequence_GetItem(result, i);
  215. if ( ob == NULL )
  216. goto error;
  217. %(converter)s
  218. {
  219. Py_DECREF(result);
  220. return PyCom_SetCOMErrorFromPyException(IID_IEnum%(enumtype)s);
  221. }
  222. }
  223. Py_DECREF(result);
  224. return len < (int)celt ? S_FALSE : S_OK;
  225. error:
  226. PyErr_Clear(); // just in case
  227. Py_DECREF(result);
  228. return PyCom_HandleIEnumNoSequence(IID_IEnum%(enumtype)s);
  229. }
  230. STDMETHODIMP PyGEnum%(enumtype)s::Skip(
  231. /* [in] */ ULONG celt)
  232. {
  233. PY_GATEWAY_METHOD;
  234. return InvokeViaPolicy("Skip", NULL, "i", celt);
  235. }
  236. STDMETHODIMP PyGEnum%(enumtype)s::Reset(void)
  237. {
  238. PY_GATEWAY_METHOD;
  239. return InvokeViaPolicy("Reset");
  240. }
  241. STDMETHODIMP PyGEnum%(enumtype)s::Clone(
  242. /* [out] */ IEnum%(enumtype)s __RPC_FAR *__RPC_FAR *ppEnum)
  243. {
  244. PY_GATEWAY_METHOD;
  245. PyObject * result;
  246. HRESULT hr = InvokeViaPolicy("Clone", &result);
  247. if ( FAILED(hr) )
  248. return hr;
  249. /*
  250. ** Make sure we have the right kind of object: we should have some kind
  251. ** of IUnknown subclass wrapped into a PyIUnknown instance.
  252. */
  253. if ( !PyIBase::is_object(result, &PyIUnknown::type) )
  254. {
  255. /* the wrong kind of object was returned to us */
  256. Py_DECREF(result);
  257. return PyCom_SetCOMErrorFromSimple(E_FAIL, IID_IEnum%(enumtype)s);
  258. }
  259. /*
  260. ** Get the IUnknown out of the thing. note that the Python ob maintains
  261. ** a reference, so we don't have to explicitly AddRef() here.
  262. */
  263. IUnknown *punk = ((PyIUnknown *)result)->m_obj;
  264. if ( !punk )
  265. {
  266. /* damn. the object was released. */
  267. Py_DECREF(result);
  268. return PyCom_SetCOMErrorFromSimple(E_FAIL, IID_IEnum%(enumtype)s);
  269. }
  270. /*
  271. ** Get the interface we want. note it is returned with a refcount.
  272. ** This QI is actually going to instantiate a PyGEnum%(enumtype)s.
  273. */
  274. hr = punk->QueryInterface(IID_IEnum%(enumtype)s, (LPVOID *)ppEnum);
  275. /* done with the result; this DECREF is also for <punk> */
  276. Py_DECREF(result);
  277. return PyCom_CheckIEnumNextResult(hr, IID_IEnum%(enumtype)s);
  278. }
  279. """
  280. % locals()
  281. )