123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- #ifndef __PYTHONCOMSERVER_H__
- #define __PYTHONCOMSERVER_H__
- // PythonCOMServer.h :Server side COM support
- #include <Python.h>
- #define DLLAcquireGlobalLock PyWin_AcquireGlobalLock
- #define DLLReleaseGlobalLock PyWin_ReleaseGlobalLock
- void PYCOM_EXPORT PyCom_DLLAddRef(void);
- void PYCOM_EXPORT PyCom_DLLReleaseRef(void);
- // Use this macro at the start of all gateway methods.
- #define PY_GATEWAY_METHOD CEnterLeavePython _celp
- class PyGatewayBase;
- // Gateway constructors.
- // Each gateway must be able to be created from a "gateway constructor". This
- // is simply a function that takes a Python instance as as argument, and returns
- // a gateway object of the correct type. The MAKE_PYGATEWAY_CTOR is a helper that
- // will embed such a constructor in the class - however, this is not necessary -
- // _any_ function of the correct signature can be used.
- typedef HRESULT (*pfnPyGatewayConstructor)(PyObject *PythonInstance, PyGatewayBase *, void **ppResult, REFIID iid);
- HRESULT PyCom_MakeRegisteredGatewayObject(REFIID iid, PyObject *instance, PyGatewayBase *base, void **ppv);
- // A version of the above which support classes being derived from
- // other than IUnknown
- #define PYGATEWAY_MAKE_SUPPORT2(classname, IInterface, theIID, gatewaybaseclass) \
- public: \
- static HRESULT classname::PyGatewayConstruct(PyObject *pPyInstance, PyGatewayBase *unkBase, void **ppResult, \
- REFIID iid) \
- { \
- if (ppResult == NULL) \
- return E_INVALIDARG; \
- classname *newob = new classname(pPyInstance); \
- newob->m_pBaseObject = unkBase; \
- if (unkBase) \
- unkBase->AddRef(); \
- *ppResult = newob->ThisAsIID(iid); \
- return *ppResult ? S_OK : E_OUTOFMEMORY; \
- } \
- \
- protected: \
- virtual IID GetIID(void) { return theIID; } \
- virtual void *ThisAsIID(IID iid) \
- { \
- if (this == NULL) \
- return NULL; \
- if (iid == theIID) \
- return (IInterface *)this; \
- else \
- return gatewaybaseclass::ThisAsIID(iid); \
- } \
- STDMETHOD_(ULONG, AddRef)(void) { return gatewaybaseclass::AddRef(); } \
- STDMETHOD_(ULONG, Release)(void) { return gatewaybaseclass::Release(); } \
- STDMETHOD(QueryInterface)(REFIID iid, void **obj) { return gatewaybaseclass::QueryInterface(iid, obj); };
- // This is the "old" version to use, or use it if you derive
- // directly from PyGatewayBase
- #define PYGATEWAY_MAKE_SUPPORT(classname, IInterface, theIID) \
- PYGATEWAY_MAKE_SUPPORT2(classname, IInterface, theIID, PyGatewayBase)
- #define GET_PYGATEWAY_CTOR(classname) classname::PyGatewayConstruct
- #ifdef _MSC_VER
- // Disable an OK warning...
- #pragma warning(disable : 4275)
- // warning C4275: non dll-interface struct 'IDispatch' used as base for dll-interface class 'PyGatewayBase'
- #endif // _MSC_VER
- // Helper interface for fetching a Python object from a gateway
- extern const GUID IID_IInternalUnwrapPythonObject;
- interface IInternalUnwrapPythonObject : public IUnknown
- {
- public:
- STDMETHOD(Unwrap)(PyObject * *ppPyObject) = 0;
- };
- /////////////////////////////////////////////////////////////////////////////
- // PyGatewayBase
- //
- // Base class for all gateways.
- //
- class PYCOM_EXPORT PyGatewayBase :
- #ifndef NO_PYCOM_IDISPATCHEX
- public IDispatchEx, // IDispatch comes along for the ride!
- #else
- public IDispatch, // No IDispatchEx - must explicitely use IDispatch
- #endif
- public ISupportErrorInfo,
- public IInternalUnwrapPythonObject {
- protected:
- PyGatewayBase(PyObject *instance);
- virtual ~PyGatewayBase();
- // Invoke the Python method (via the policy object)
- STDMETHOD(InvokeViaPolicy)(const char *szMethodName, PyObject **ppResult = NULL, const char *szFormat = NULL, ...);
- public:
- // IUnknown
- STDMETHOD_(ULONG, AddRef)(void);
- STDMETHOD_(ULONG, Release)(void);
- STDMETHOD(QueryInterface)(REFIID iid, void **obj);
- // IDispatch
- STDMETHOD(GetTypeInfoCount)(UINT FAR *pctInfo);
- STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo FAR *FAR *pptInfo);
- STDMETHOD(GetIDsOfNames)(REFIID refiid, OLECHAR FAR *FAR *rgszNames, UINT cNames, LCID lcid, DISPID FAR *rgdispid);
- STDMETHOD(Invoke)
- (DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *params, VARIANT FAR *pVarResult,
- EXCEPINFO FAR *pexcepinfo, UINT FAR *puArgErr);
- // IDispatchEx
- #ifndef NO_PYCOM_IDISPATCHEX
- STDMETHOD(GetDispID)(BSTR bstrName, DWORD grfdex, DISPID *pid);
- STDMETHOD(InvokeEx)
- (DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller);
- STDMETHOD(DeleteMemberByName)(BSTR bstr, DWORD grfdex);
- STDMETHOD(DeleteMemberByDispID)(DISPID id);
- STDMETHOD(GetMemberProperties)(DISPID id, DWORD grfdexFetch, DWORD *pgrfdex);
- STDMETHOD(GetMemberName)(DISPID id, BSTR *pbstrName);
- STDMETHOD(GetNextDispID)(DWORD grfdex, DISPID id, DISPID *pid);
- STDMETHOD(GetNameSpaceParent)(IUnknown **ppunk);
- #endif // NO_PYCOM_IDISPATCHEX
- // ISupportErrorInfo
- STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
- // IInternalUnwrapPythonObject
- STDMETHOD(Unwrap)(PyObject **ppPyObject);
- // Basically just PYGATEWAY_MAKE_SUPPORT(PyGatewayBase, IDispatch, IID_IDispatch);
- // but with special handling as its the base class.
- static HRESULT PyGatewayBase::PyGatewayConstruct(PyObject *pPyInstance, PyGatewayBase *gatewayBase, void **ppResult,
- REFIID iid)
- {
- if (ppResult == NULL)
- return E_INVALIDARG;
- PyGatewayBase *obNew = new PyGatewayBase(pPyInstance);
- obNew->m_pBaseObject = gatewayBase;
- if (gatewayBase)
- gatewayBase->AddRef();
- *ppResult = (IDispatch *)obNew;
- return *ppResult ? S_OK : E_OUTOFMEMORY;
- }
- // Currently this is used only for ISupportErrorInfo,
- // so hopefully this will never be called in this base class.
- // (however, this is not a rule, so we wont assert or anything!)
- virtual IID GetIID(void) { return IID_IUnknown; }
- virtual void *ThisAsIID(IID iid);
- // End of PYGATEWAY_MAKE_SUPPORT
- PyObject *m_pPyObject;
- PyGatewayBase *m_pBaseObject;
- private:
- LONG m_cRef;
- };
- #ifdef _MSC_VER
- #pragma warning(default : 4275)
- #endif // _MSC_VER
- // B/W compat hack for gateways.
- #define PyCom_HandlePythonFailureToCOM() \
- PyCom_SetAndLogCOMErrorFromPyExceptionEx(this->m_pPyObject, "<unknown>", GetIID())
- // F/W compat hack for gateways! Must be careful about updating
- // PyGatewayBase vtable, so a slightly older pythoncomXX.dll will work
- // with slightly later extensions. So use a #define.
- #define MAKE_PYCOM_GATEWAY_FAILURE_CODE(method_name) \
- PyCom_SetAndLogCOMErrorFromPyExceptionEx(this->m_pPyObject, method_name, GetIID())
- #endif /* __PYTHONCOMSERVER_H__ */
|