home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Shareware / Comunicatii / jyte / jyte.exe / makegwenum.py < prev    next >
Text File  |  2000-01-05  |  10KB  |  318 lines

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