/ lib / win32com / include / PythonCOMServer.h
PythonCOMServer.h
  1  #ifndef __PYTHONCOMSERVER_H__
  2  #define __PYTHONCOMSERVER_H__
  3  
  4  // PythonCOMServer.h :Server side COM support
  5  
  6  #include <Python.h>
  7  
  8  #define DLLAcquireGlobalLock PyWin_AcquireGlobalLock
  9  #define DLLReleaseGlobalLock PyWin_ReleaseGlobalLock
 10  
 11  void PYCOM_EXPORT PyCom_DLLAddRef(void);
 12  void PYCOM_EXPORT PyCom_DLLReleaseRef(void);
 13  
 14  // Use this macro at the start of all gateway methods.
 15  #define PY_GATEWAY_METHOD CEnterLeavePython _celp
 16  
 17  class PyGatewayBase;
 18  // Gateway constructors.
 19  // Each gateway must be able to be created from a "gateway constructor".  This
 20  // is simply a function that takes a Python instance as as argument, and returns
 21  // a gateway object of the correct type.  The MAKE_PYGATEWAY_CTOR is a helper that
 22  // will embed such a constructor in the class - however, this is not necessary -
 23  // _any_ function of the correct signature can be used.
 24  
 25  typedef HRESULT (*pfnPyGatewayConstructor)(PyObject *PythonInstance, PyGatewayBase *, void **ppResult, REFIID iid);
 26  HRESULT PyCom_MakeRegisteredGatewayObject(REFIID iid, PyObject *instance, PyGatewayBase *base, void **ppv);
 27  
 28  // A version of the above which support classes being derived from
 29  // other than IUnknown
 30  #define PYGATEWAY_MAKE_SUPPORT2(classname, IInterface, theIID, gatewaybaseclass)                                 \
 31     public:                                                                                                       \
 32      static HRESULT classname::PyGatewayConstruct(PyObject *pPyInstance, PyGatewayBase *unkBase, void **ppResult, \
 33                                                   REFIID iid)                                                     \
 34      {                                                                                                            \
 35          if (ppResult == NULL)                                                                                    \
 36              return E_INVALIDARG;                                                                                 \
 37          classname *newob = new classname(pPyInstance);                                                           \
 38          newob->m_pBaseObject = unkBase;                                                                          \
 39          if (unkBase)                                                                                             \
 40              unkBase->AddRef();                                                                                   \
 41          *ppResult = newob->ThisAsIID(iid);                                                                       \
 42          return *ppResult ? S_OK : E_OUTOFMEMORY;                                                                 \
 43      }                                                                                                            \
 44                                                                                                                   \
 45     protected:                                                                                                    \
 46      virtual IID GetIID(void) { return theIID; }                                                                  \
 47      virtual void *ThisAsIID(IID iid)                                                                             \
 48      {                                                                                                            \
 49          if (this == NULL)                                                                                        \
 50              return NULL;                                                                                         \
 51          if (iid == theIID)                                                                                       \
 52              return (IInterface *)this;                                                                           \
 53          else                                                                                                     \
 54              return gatewaybaseclass::ThisAsIID(iid);                                                             \
 55      }                                                                                                            \
 56      STDMETHOD_(ULONG, AddRef)(void) { return gatewaybaseclass::AddRef(); }                                       \
 57      STDMETHOD_(ULONG, Release)(void) { return gatewaybaseclass::Release(); }                                     \
 58      STDMETHOD(QueryInterface)(REFIID iid, void **obj) { return gatewaybaseclass::QueryInterface(iid, obj); };
 59  
 60  // This is the "old" version to use, or use it if you derive
 61  // directly from PyGatewayBase
 62  #define PYGATEWAY_MAKE_SUPPORT(classname, IInterface, theIID) \
 63      PYGATEWAY_MAKE_SUPPORT2(classname, IInterface, theIID, PyGatewayBase)
 64  
 65  #define GET_PYGATEWAY_CTOR(classname) classname::PyGatewayConstruct
 66  
 67  #ifdef _MSC_VER
 68  // Disable an OK warning...
 69  #pragma warning(disable : 4275)
 70  // warning C4275: non dll-interface struct 'IDispatch' used as base for dll-interface class 'PyGatewayBase'
 71  #endif  // _MSC_VER
 72  
 73  // Helper interface for fetching a Python object from a gateway
 74  
 75  extern const GUID IID_IInternalUnwrapPythonObject;
 76  
 77  interface IInternalUnwrapPythonObject : public IUnknown
 78  {
 79     public:
 80      STDMETHOD(Unwrap)(PyObject * *ppPyObject) = 0;
 81  };
 82  
 83  /////////////////////////////////////////////////////////////////////////////
 84  // PyGatewayBase
 85  //
 86  // Base class for all gateways.
 87  //
 88  class PYCOM_EXPORT PyGatewayBase :
 89  #ifndef NO_PYCOM_IDISPATCHEX
 90      public IDispatchEx,  // IDispatch comes along for the ride!
 91  #else
 92      public IDispatch,  // No IDispatchEx - must explicitely use IDispatch
 93  #endif
 94      public ISupportErrorInfo,
 95      public IInternalUnwrapPythonObject {
 96     protected:
 97      PyGatewayBase(PyObject *instance);
 98      virtual ~PyGatewayBase();
 99  
100      // Invoke the Python method (via the policy object)
101      STDMETHOD(InvokeViaPolicy)(const char *szMethodName, PyObject **ppResult = NULL, const char *szFormat = NULL, ...);
102  
103     public:
104      // IUnknown
105      STDMETHOD_(ULONG, AddRef)(void);
106      STDMETHOD_(ULONG, Release)(void);
107      STDMETHOD(QueryInterface)(REFIID iid, void **obj);
108  
109      // IDispatch
110      STDMETHOD(GetTypeInfoCount)(UINT FAR *pctInfo);
111      STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo FAR *FAR *pptInfo);
112      STDMETHOD(GetIDsOfNames)(REFIID refiid, OLECHAR FAR *FAR *rgszNames, UINT cNames, LCID lcid, DISPID FAR *rgdispid);
113      STDMETHOD(Invoke)
114      (DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *params, VARIANT FAR *pVarResult,
115       EXCEPINFO FAR *pexcepinfo, UINT FAR *puArgErr);
116  
117      // IDispatchEx
118  #ifndef NO_PYCOM_IDISPATCHEX
119      STDMETHOD(GetDispID)(BSTR bstrName, DWORD grfdex, DISPID *pid);
120      STDMETHOD(InvokeEx)
121      (DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller);
122      STDMETHOD(DeleteMemberByName)(BSTR bstr, DWORD grfdex);
123      STDMETHOD(DeleteMemberByDispID)(DISPID id);
124      STDMETHOD(GetMemberProperties)(DISPID id, DWORD grfdexFetch, DWORD *pgrfdex);
125      STDMETHOD(GetMemberName)(DISPID id, BSTR *pbstrName);
126      STDMETHOD(GetNextDispID)(DWORD grfdex, DISPID id, DISPID *pid);
127      STDMETHOD(GetNameSpaceParent)(IUnknown **ppunk);
128  #endif  // NO_PYCOM_IDISPATCHEX
129      // ISupportErrorInfo
130      STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
131  
132      // IInternalUnwrapPythonObject
133      STDMETHOD(Unwrap)(PyObject **ppPyObject);
134  
135      // Basically just PYGATEWAY_MAKE_SUPPORT(PyGatewayBase, IDispatch, IID_IDispatch);
136      // but with special handling as its the base class.
137      static HRESULT PyGatewayBase::PyGatewayConstruct(PyObject *pPyInstance, PyGatewayBase *gatewayBase, void **ppResult,
138                                                       REFIID iid)
139      {
140          if (ppResult == NULL)
141              return E_INVALIDARG;
142          PyGatewayBase *obNew = new PyGatewayBase(pPyInstance);
143          obNew->m_pBaseObject = gatewayBase;
144          if (gatewayBase)
145              gatewayBase->AddRef();
146          *ppResult = (IDispatch *)obNew;
147          return *ppResult ? S_OK : E_OUTOFMEMORY;
148      }
149      // Currently this is used only for ISupportErrorInfo,
150      // so hopefully this will never be called in this base class.
151      // (however, this is not a rule, so we wont assert or anything!)
152      virtual IID GetIID(void) { return IID_IUnknown; }
153      virtual void *ThisAsIID(IID iid);
154      // End of PYGATEWAY_MAKE_SUPPORT
155      PyObject *m_pPyObject;
156      PyGatewayBase *m_pBaseObject;
157  
158     private:
159      LONG m_cRef;
160  };
161  
162  #ifdef _MSC_VER
163  #pragma warning(default : 4275)
164  #endif  // _MSC_VER
165  
166  // B/W compat hack for gateways.
167  #define PyCom_HandlePythonFailureToCOM() \
168      PyCom_SetAndLogCOMErrorFromPyExceptionEx(this->m_pPyObject, "<unknown>", GetIID())
169  
170  // F/W compat hack for gateways!  Must be careful about updating
171  // PyGatewayBase vtable, so a slightly older pythoncomXX.dll will work
172  // with slightly later extensions.  So use a #define.
173  #define MAKE_PYCOM_GATEWAY_FAILURE_CODE(method_name) \
174      PyCom_SetAndLogCOMErrorFromPyExceptionEx(this->m_pPyObject, method_name, GetIID())
175  
176  #endif /* __PYTHONCOMSERVER_H__ */