install pywin32-220
This commit is contained in:
parent
15d9012f5a
commit
93f7d415a0
581 changed files with 100203 additions and 0 deletions
787
Lib/site-packages/win32com/include/PythonCOM.h
Normal file
787
Lib/site-packages/win32com/include/PythonCOM.h
Normal file
|
|
@ -0,0 +1,787 @@
|
|||
/* PythonCOM.h
|
||||
|
||||
Main header for Python COM support.
|
||||
|
||||
This file is involved mainly with client side COM support for
|
||||
Python.
|
||||
|
||||
Most COM work put together by Greg Stein and Mark Hammond, with a
|
||||
few others starting to come out of the closet.
|
||||
|
||||
|
||||
--------------------------------------------------------------------
|
||||
Thread State Rules
|
||||
------------------
|
||||
These rules apply to PythonCOM in general, and not just to
|
||||
the client side.
|
||||
|
||||
The rules are quite simple, but it is critical they be followed.
|
||||
In general, errors here will be picked up quite quickly, as Python
|
||||
will raise a Fatal Error. However, the Release() issue in particular
|
||||
may keep a number of problems well hidden.
|
||||
|
||||
Interfaces:
|
||||
-----------
|
||||
Before making ANY call out to COM, you MUST release the Python lock.
|
||||
This is true to ANY call whatsoever, including the COM call in question,
|
||||
but also any calls to "->Release();"
|
||||
|
||||
This is normally achieved with the calls
|
||||
PY_INTERFACE_PRECALL and PY_INTERFACE_POSTCALL, which release
|
||||
and acquire the Python lock.
|
||||
|
||||
Gateways:
|
||||
---------
|
||||
Before doing anything related to Python, gateways MUST acquire the
|
||||
Python lock, and must release it before returning.
|
||||
|
||||
This is normally achieved with PY_GATEWAY_METHOD at the top of a
|
||||
gateway method. This macro resolves to a class, which automatically does
|
||||
the right thing.
|
||||
|
||||
Release:
|
||||
--------
|
||||
As mentioned above for Interfaces, EVERY call to Release() must be done
|
||||
with the Python lock released. This is expanded here.
|
||||
|
||||
This is very important, but an error may not be noticed. The problem will
|
||||
only be seen when the Release() is on a Python object and the Release() is the
|
||||
final one for the object. In this case, the Python object will attempt to
|
||||
acquire the Python lock before destroying itself, and Python will raise a
|
||||
fatal error.
|
||||
|
||||
In many many cases, you will not notice this error, but someday, someone will
|
||||
implement the other side in Python, and suddenly FatalErrors will start
|
||||
appearing. Make sure you get this right.
|
||||
|
||||
Eg, this code is correct:
|
||||
PY_INTERFACE_PRECALL;
|
||||
pSomeObj->SomeFunction(pSomeOtherObject);
|
||||
pSomeOtherObject->Release();
|
||||
PY_INTERFACE_POSTCALL;
|
||||
|
||||
However, this code is WRONG, but will RARELY FAIL.
|
||||
PY_INTERFACE_PRECALL;
|
||||
pSomeObj->SomeFunction(pSomeOtherObject);
|
||||
PY_INTERFACE_POSTCALL;
|
||||
pSomeOtherObject->Release();
|
||||
--------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef __PYTHONCOM_H__
|
||||
#define __PYTHONCOM_H__
|
||||
|
||||
// #define _DEBUG_LIFETIMES // Trace COM object lifetimes.
|
||||
|
||||
#ifdef FREEZE_PYTHONCOM
|
||||
/* The pythoncom module is being included in a frozen .EXE/.DLL */
|
||||
# define PYCOM_EXPORT
|
||||
#else
|
||||
# ifdef BUILD_PYTHONCOM
|
||||
/* We are building pythoncomxx.dll */
|
||||
# define PYCOM_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
/* This module uses pythoncomxx.dll */
|
||||
# define PYCOM_EXPORT __declspec(dllimport)
|
||||
# ifndef _DEBUG
|
||||
# pragma comment(lib, "pythoncom.lib")
|
||||
# else
|
||||
# pragma comment(lib, "pythoncom_d.lib")
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef MS_WINCE
|
||||
// List of interfaces not supported by CE.
|
||||
#define NO_PYCOM_IDISPATCHEX
|
||||
#define NO_PYCOM_IPROVIDECLASSINFO
|
||||
#define NO_PYCOM_IENUMGUID
|
||||
#define NO_PYCOM_IENUMCATEGORYINFO
|
||||
#define NO_PYCOM_ICATINFORMATION
|
||||
#define NO_PYCOM_ICATREGISTER
|
||||
#define NO_PYCOM_ISERVICEPROVIDER
|
||||
#define NO_PYCOM_IPROPERTYSTORAGE
|
||||
#define NO_PYCOM_IPROPERTYSETSTORAGE
|
||||
#define NO_PYCOM_ENUMSTATPROPSTG
|
||||
|
||||
#include "ocidl.h"
|
||||
#include "oleauto.h"
|
||||
|
||||
#endif // MS_WINCE
|
||||
|
||||
#ifdef __MINGW32__
|
||||
// Special Mingw32 considerations.
|
||||
#define NO_PYCOM_IDISPATCHEX
|
||||
#define NO_PYCOM_IPROVIDECLASSINFO
|
||||
#define NO_PYCOM_ISERVICEPROVIDER
|
||||
#define NO_PYCOM_ENUMSTATPROPSTG
|
||||
#define NO_PYCOM_IPROPERTYSTORAGE
|
||||
#define __try try
|
||||
#define __except catch
|
||||
#include <olectl.h>
|
||||
|
||||
#endif // __MINGW32__
|
||||
|
||||
#include <PyWinTypes.h> // Standard Win32 Types
|
||||
|
||||
#ifndef NO_PYCOM_IDISPATCHEX
|
||||
#include <dispex.h> // New header for IDispatchEx interface.
|
||||
#endif // NO_PYCOM_IDISPATCHEX
|
||||
|
||||
#if defined(MAINWIN)
|
||||
// Mainwin seems to have 1/2 the VT_RECORD infrastructure in place
|
||||
# if !defined(VT_RECORD)
|
||||
# define VT_RECORD 36
|
||||
# define V_RECORDINFO(X) ((X)->brecVal.pRecInfo)
|
||||
# define V_RECORD(X) ((X)->brecVal.pvRecord)
|
||||
# else
|
||||
# pragma message("MAINWIN appears to have grown correct VT_RECORD " \
|
||||
"support. Please update PythonCOM.h accordingly")
|
||||
# endif //VT_RECORD
|
||||
#endif // MAINWIN
|
||||
|
||||
class PyIUnknown;
|
||||
// To make life interesting/complicated, I use C++ classes for
|
||||
// all Python objects. The main advantage is that I can derive
|
||||
// a PyIDispatch object from a PyIUnknown, etc. This provides a
|
||||
// clean C++ interface, and "automatically" provides all base
|
||||
// Python methods to "derived" Python types.
|
||||
//
|
||||
// Main disadvantage is that any extension DLLs will need to include
|
||||
// these headers, and link with this .lib
|
||||
//
|
||||
// Base class for (most of) the type objects.
|
||||
|
||||
class PYCOM_EXPORT PyComTypeObject : public PyTypeObject {
|
||||
public:
|
||||
PyComTypeObject( const char *name, PyComTypeObject *pBaseType, int typeSize, struct PyMethodDef* methodList, PyIUnknown* (* thector)(IUnknown *) );
|
||||
~PyComTypeObject();
|
||||
|
||||
// is the given object an interface type object? (e.g. PyIUnknown)
|
||||
static BOOL is_interface_type(PyObject *ob);
|
||||
|
||||
public:
|
||||
PyIUnknown * (* ctor)(IUnknown *);
|
||||
};
|
||||
|
||||
// A type used for interfaces that can automatically provide enumerators
|
||||
// (ie, they themselves aren't enumerable, but do have a suitable default
|
||||
// method that returns a PyIEnum object
|
||||
class PYCOM_EXPORT PyComEnumProviderTypeObject : public PyComTypeObject {
|
||||
public:
|
||||
PyComEnumProviderTypeObject( const char *name,
|
||||
PyComTypeObject *pBaseType,
|
||||
int typeSize,
|
||||
struct PyMethodDef* methodList,
|
||||
PyIUnknown* (* thector)(IUnknown *),
|
||||
const char *enum_method_name);
|
||||
static PyObject *iter(PyObject *self);
|
||||
const char *enum_method_name;
|
||||
};
|
||||
|
||||
// A type used for PyIEnum interfaces
|
||||
class PYCOM_EXPORT PyComEnumTypeObject : public PyComTypeObject {
|
||||
public:
|
||||
static PyObject *iter(PyObject *self);
|
||||
static PyObject *iternext(PyObject *self);
|
||||
PyComEnumTypeObject( const char *name, PyComTypeObject *pBaseType, int typeSize, struct PyMethodDef* methodList, PyIUnknown* (* thector)(IUnknown *) );
|
||||
};
|
||||
|
||||
// Very very base class - not COM specific - Should exist in the
|
||||
// Python core somewhere, IMO.
|
||||
class PYCOM_EXPORT PyIBase :
|
||||
public PyObject
|
||||
{
|
||||
public:
|
||||
// virtuals for Python support
|
||||
virtual PyObject *getattr(char *name);
|
||||
virtual int setattr(char *name, PyObject *v);
|
||||
virtual PyObject *repr();
|
||||
virtual int compare(PyObject *other) {
|
||||
if (this == other)
|
||||
return 0;
|
||||
if (this < other)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
// These iter are a little special, in that returning NULL means
|
||||
// use the implementation in the type
|
||||
virtual PyObject *iter() {return NULL;}
|
||||
virtual PyObject *iternext() {return NULL;}
|
||||
protected:
|
||||
PyIBase();
|
||||
virtual ~PyIBase();
|
||||
|
||||
public:
|
||||
static BOOL is_object(PyObject *, PyComTypeObject *which);
|
||||
BOOL is_object(PyComTypeObject *which);
|
||||
static void dealloc(PyObject *ob);
|
||||
static PyObject *repr(PyObject *ob);
|
||||
static PyObject *getattro(PyObject *self, PyObject *name);
|
||||
static int setattro(PyObject *op, PyObject *obname, PyObject *v);
|
||||
static int cmp(PyObject *ob1, PyObject *ob2);
|
||||
static PyObject *richcmp(PyObject *ob1, PyObject *ob2, int op);
|
||||
|
||||
};
|
||||
|
||||
/* Special Type objects */
|
||||
extern PYCOM_EXPORT PyTypeObject PyOleEmptyType; // equivalent to VT_EMPTY
|
||||
extern PYCOM_EXPORT PyTypeObject PyOleMissingType; // special Python handling.
|
||||
extern PYCOM_EXPORT PyTypeObject PyOleArgNotFoundType; // special VT_ERROR value
|
||||
extern PYCOM_EXPORT PyTypeObject PyOleNothingType; // special VT_ERROR value
|
||||
|
||||
// ALL of these set an appropriate Python error on bad return.
|
||||
|
||||
// Given a Python object that is a registered COM type, return a given
|
||||
// interface pointer on its underlying object, with a new reference added.
|
||||
PYCOM_EXPORT BOOL PyCom_InterfaceFromPyObject(
|
||||
PyObject *ob,
|
||||
REFIID iid,
|
||||
LPVOID *ppv,
|
||||
BOOL bNoneOK=TRUE
|
||||
);
|
||||
|
||||
// As above, but allows instance with "_oleobj_" attribute.
|
||||
PYCOM_EXPORT BOOL PyCom_InterfaceFromPyInstanceOrObject(
|
||||
PyObject *ob,
|
||||
REFIID iid,
|
||||
LPVOID *ppv,
|
||||
BOOL bNoneOK=TRUE
|
||||
);
|
||||
|
||||
// Release an arbitary COM pointer.
|
||||
// NOTE: the PRECALL/POSTCALL stuff is probably not strictly necessary
|
||||
// since the PyGILSTATE stuff has been in place (and even then, it only
|
||||
// mattered when it was the last Release() on a Python implemented object)
|
||||
#define PYCOM_RELEASE(pUnk) { \
|
||||
if (pUnk) { \
|
||||
PY_INTERFACE_PRECALL; \
|
||||
(pUnk)->Release(); \
|
||||
PY_INTERFACE_POSTCALL; \
|
||||
} \
|
||||
}
|
||||
|
||||
// Given an IUnknown and an Interface ID, create and return an object
|
||||
// of the appropriate type. eg IID_Unknown->PyIUnknown,
|
||||
// IID_IDispatch->PyIDispatch, etc.
|
||||
// Uses a map that external extension DLLs can populate with their IID/type.
|
||||
// Under the principal of least surprise, this will return Py_None is punk is NULL.
|
||||
// Otherwise, a valid PyI*, but with NULL m_obj (and therefore totally useless)
|
||||
// object would be created.
|
||||
// BOOL bAddRef indicates if a COM reference count should be added to the IUnknown.
|
||||
// This depends purely on the context in which it is called. If the IUnknown is obtained
|
||||
// from a function that creates a new ref (eg, CoCreateInstance()) then you should use
|
||||
// FALSE. If you receive the pointer as (eg) a param to a gateway function, then
|
||||
// you normally need to pass TRUE, as this is truly a new reference.
|
||||
// *** ALWAYS take the time to get this right. ***
|
||||
PYCOM_EXPORT PyObject *PyCom_PyObjectFromIUnknown(IUnknown *punk, REFIID riid, BOOL bAddRef = FALSE);
|
||||
|
||||
// VARIANT <-> PyObject conversion utilities.
|
||||
PYCOM_EXPORT BOOL PyCom_VariantFromPyObject(PyObject *obj, VARIANT *var);
|
||||
PYCOM_EXPORT PyObject *PyCom_PyObjectFromVariant(const VARIANT *var);
|
||||
|
||||
// PROPVARIANT
|
||||
PYCOM_EXPORT PyObject *PyObject_FromPROPVARIANT( PROPVARIANT *pVar );
|
||||
PYCOM_EXPORT PyObject *PyObject_FromPROPVARIANTs( PROPVARIANT *pVars, ULONG cVars );
|
||||
PYCOM_EXPORT BOOL PyObject_AsPROPVARIANT(PyObject *ob, PROPVARIANT *pVar);
|
||||
|
||||
// Other conversion helpers...
|
||||
PYCOM_EXPORT PyObject *PyCom_PyObjectFromSTATSTG(STATSTG *pStat);
|
||||
PYCOM_EXPORT BOOL PyCom_PyObjectAsSTATSTG(PyObject *ob, STATSTG *pStat, DWORD flags = 0);
|
||||
PYCOM_EXPORT BOOL PyCom_SAFEARRAYFromPyObject(PyObject *obj, SAFEARRAY **ppSA, VARENUM vt = VT_VARIANT);
|
||||
PYCOM_EXPORT PyObject *PyCom_PyObjectFromSAFEARRAY(SAFEARRAY *psa, VARENUM vt = VT_VARIANT );
|
||||
#ifndef NO_PYCOM_STGOPTIONS
|
||||
PYCOM_EXPORT BOOL PyCom_PyObjectAsSTGOPTIONS(PyObject *obstgoptions, STGOPTIONS **ppstgoptions);
|
||||
#endif
|
||||
PYCOM_EXPORT PyObject *PyCom_PyObjectFromSTATPROPSETSTG(STATPROPSETSTG *pStat);
|
||||
PYCOM_EXPORT BOOL PyCom_PyObjectAsSTATPROPSETSTG(PyObject *, STATPROPSETSTG *);
|
||||
|
||||
// Currency support.
|
||||
PYCOM_EXPORT PyObject *PyObject_FromCurrency(CURRENCY &cy);
|
||||
PYCOM_EXPORT BOOL PyObject_AsCurrency(PyObject *ob, CURRENCY *pcy);
|
||||
|
||||
// OLEMENUGROUPWIDTHS are used by axcontrol, shell, etc
|
||||
PYCOM_EXPORT BOOL PyObject_AsOLEMENUGROUPWIDTHS( PyObject *oblpMenuWidths, OLEMENUGROUPWIDTHS *pWidths);
|
||||
PYCOM_EXPORT PyObject *PyObject_FromOLEMENUGROUPWIDTHS(const OLEMENUGROUPWIDTHS *pWidths);
|
||||
|
||||
/* Functions for Initializing COM, and also letting the core know about it!
|
||||
*/
|
||||
PYCOM_EXPORT HRESULT PyCom_CoInitializeEx(LPVOID reserved, DWORD dwInit);
|
||||
PYCOM_EXPORT HRESULT PyCom_CoInitialize(LPVOID reserved);
|
||||
PYCOM_EXPORT void PyCom_CoUninitialize();
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Error related functions
|
||||
|
||||
// Client related functions - generally called by interfaces before
|
||||
// they return NULL back to Python to indicate the error.
|
||||
// All these functions return NULL so interfaces can generally
|
||||
// just "return PyCom_BuildPyException(hr, punk, IID_IWhatever)"
|
||||
|
||||
// Uses the HRESULT, and IErrorInfo interfaces if available to
|
||||
// create and set a pythoncom.com_error.
|
||||
PYCOM_EXPORT PyObject *PyCom_BuildPyException(HRESULT hr, IUnknown *pUnk=NULL, REFIID iid=IID_NULL);
|
||||
|
||||
// Uses the HRESULT and an EXCEPINFO structure to create and
|
||||
// set a pythoncom.com_error.
|
||||
PYCOM_EXPORT PyObject* PyCom_BuildPyExceptionFromEXCEPINFO(HRESULT hr, EXCEPINFO *pexcepInfo, UINT nArgErr = (UINT)-1);
|
||||
|
||||
// Sets a pythoncom.internal_error - no one should ever see these!
|
||||
PYCOM_EXPORT PyObject* PyCom_BuildInternalPyException(char *msg);
|
||||
|
||||
// Log an error to a Python logger object if one can be found, or
|
||||
// to stderr if no log available.
|
||||
// If logProvider is not NULL, we will call a "_GetLogger_()" method on it.
|
||||
// If logProvider is NULL, we attempt to fetch "win32com.logger".
|
||||
// If they do not exist, return None, or raise an error fetching them
|
||||
// (or even writing to them once fetched), the message still goes to stderr.
|
||||
// NOTE: By default, win32com does *not* provide a logger, so default is that
|
||||
// all errors are written to stdout.
|
||||
// This will *not* write a record if a COM Server error is current.
|
||||
PYCOM_EXPORT void PyCom_LoggerNonServerException(PyObject *logProvider,
|
||||
const char *fmt, ...);
|
||||
|
||||
// Write an error record, including exception. This will write an error
|
||||
// record even if a COM server error is current.
|
||||
PYCOM_EXPORT void PyCom_LoggerException(PyObject *logProvider, const char *fmt, ...);
|
||||
|
||||
// Write a warning record - in general this does *not* mean a call failed, but
|
||||
// still is something in the programmers control that they should change.
|
||||
// XXX - if an exception is pending when this is called, the traceback will
|
||||
// also be written. This is undesirable and will be changed should this
|
||||
// start being a problem.
|
||||
PYCOM_EXPORT void PyCom_LoggerWarning(PyObject *logProvider, const char *fmt, ...);
|
||||
|
||||
// Server related error functions
|
||||
// These are supplied so that any Python errors we detect can be
|
||||
// converted into COM error information. The HRESULT returned should
|
||||
// be returned by the COM function, and these functions also set the
|
||||
// IErrorInfo interfaces, so the caller can extract more detailed
|
||||
// information about the Python exception.
|
||||
|
||||
// Set a COM exception, logging the exception if not an explicitly raised 'server' exception
|
||||
PYCOM_EXPORT HRESULT PyCom_SetAndLogCOMErrorFromPyException(const char *methodName, REFIID riid /* = IID_NULL */);
|
||||
PYCOM_EXPORT HRESULT PyCom_SetAndLogCOMErrorFromPyExceptionEx(PyObject *provider, const char *methodName, REFIID riid /* = IID_NULL */);
|
||||
|
||||
// Used in gateways to SetErrorInfo() with a simple HRESULT, then return it.
|
||||
// The description is generally only useful for debugging purposes,
|
||||
// and if you are debugging via a server that supports IErrorInfo (like Python :-)
|
||||
// NOTE: this function is usuable from outside the Python context
|
||||
PYCOM_EXPORT HRESULT PyCom_SetCOMErrorFromSimple(HRESULT hr, REFIID riid = IID_NULL, const char *description = NULL);
|
||||
|
||||
// Used in gateways to SetErrorInfo() the current Python exception, and
|
||||
// (assuming not a server error explicitly raised) also logs an error
|
||||
// to stdout/win32com.logger.
|
||||
// NOTE: this function assumes GIL held
|
||||
PYCOM_EXPORT HRESULT PyCom_SetCOMErrorFromPyException(REFIID riid = IID_NULL);
|
||||
|
||||
// A couple of EXCEPINFO helpers - could be private to IDispatch
|
||||
// if it wasnt for the AXScript support (and ITypeInfo if we get around to that :-)
|
||||
// These functions do not set any error states to either Python or
|
||||
// COM - they simply convert to/from PyObjects and EXCEPINFOs
|
||||
|
||||
// Use the current Python exception to fill an EXCEPINFO structure.
|
||||
PYCOM_EXPORT void PyCom_ExcepInfoFromPyException(EXCEPINFO *pExcepInfo);
|
||||
|
||||
// Fill in an EXCEPINFO structure from a Python instance or tuple object.
|
||||
// (ie, similar to the above, except the Python exception object is specified,
|
||||
// rather than using the "current"
|
||||
PYCOM_EXPORT BOOL PyCom_ExcepInfoFromPyObject(PyObject *obExcepInfo, EXCEPINFO *pexcepInfo, HRESULT *phresult = NULL);
|
||||
|
||||
// Create a Python object holding the exception information. The exception
|
||||
// information is *not* freed by this function. Python exceptions are
|
||||
// raised and NULL is returned if an error occurs.
|
||||
PYCOM_EXPORT PyObject *PyCom_PyObjectFromExcepInfo(const EXCEPINFO *pexcepInfo);
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// External C++ helpers - these helpers are for other DLLs which
|
||||
// may need similar functionality, but dont want to duplicate all
|
||||
|
||||
// This helper is for an application that has an IDispatch, and COM arguments
|
||||
// and wants to call a Python function. It is assumed the caller can map the IDispatch
|
||||
// to a Python object, so the Python handler is passed.
|
||||
// Args:
|
||||
// handler : A Python callable object.
|
||||
// dispparms : the COM arguments.
|
||||
// pVarResult : The variant for the return value of the Python call.
|
||||
// pexcepinfo : Exception info the helper may fill out.
|
||||
// puArgErr : Argument error the helper may fill out on exception
|
||||
// addnArgs : Any additional arguments to the Python function. May be NULL.
|
||||
// If addnArgs is NULL, then it is assumed the Python call should be native -
|
||||
// ie, the COM args are packed as normal Python args to the call.
|
||||
// If addnArgs is NOT NULL, it is assumed the Python function itself is
|
||||
// a helper. This Python function will be called with 2 arguments - both
|
||||
// tuples - first one is the COM args, second is the addn args.
|
||||
PYCOM_EXPORT BOOL PyCom_MakeOlePythonCall(PyObject *handler, DISPPARAMS FAR* params, VARIANT FAR* pVarResult,
|
||||
EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr, PyObject *addnlArgs);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Various special purpose singletons
|
||||
class PYCOM_EXPORT PyOleEmpty : public PyObject
|
||||
{
|
||||
public:
|
||||
PyOleEmpty();
|
||||
};
|
||||
|
||||
class PYCOM_EXPORT PyOleMissing : public PyObject
|
||||
{
|
||||
public:
|
||||
PyOleMissing();
|
||||
};
|
||||
|
||||
class PYCOM_EXPORT PyOleArgNotFound : public PyObject
|
||||
{
|
||||
public:
|
||||
PyOleArgNotFound();
|
||||
};
|
||||
|
||||
class PYCOM_EXPORT PyOleNothing : public PyObject
|
||||
{
|
||||
public:
|
||||
PyOleNothing();
|
||||
};
|
||||
|
||||
|
||||
// We need to dynamically create C++ Python objects
|
||||
// These helpers allow each type object to create it.
|
||||
#define MAKE_PYCOM_CTOR(classname) static PyIUnknown * classname::PyObConstruct(IUnknown *pInitObj) {return new classname(pInitObj);}
|
||||
#define MAKE_PYCOM_CTOR_ERRORINFO(classname, iid) \
|
||||
static PyIUnknown * classname::PyObConstruct(IUnknown *pInitObj) {return new classname(pInitObj);} \
|
||||
static PyObject *SetPythonCOMError(PyObject *self, HRESULT hr) {return PyCom_BuildPyException(hr, GetI(self), iid);}
|
||||
#define GET_PYCOM_CTOR(classname) classname::PyObConstruct
|
||||
|
||||
// Macros that interfaces should use. PY_INTERFACE_METHOD at the top of the method
|
||||
// The other 2 wrap directly around the underlying method call.
|
||||
#define PY_INTERFACE_METHOD
|
||||
// Identical to Py_BEGIN_ALLOW_THREADS except no { !!!
|
||||
#define PY_INTERFACE_PRECALL PyThreadState *_save = PyEval_SaveThread();
|
||||
#define PY_INTERFACE_POSTCALL PyEval_RestoreThread(_save);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// class PyIUnknown
|
||||
class PYCOM_EXPORT PyIUnknown : public PyIBase
|
||||
{
|
||||
public:
|
||||
MAKE_PYCOM_CTOR(PyIUnknown);
|
||||
virtual PyObject *repr();
|
||||
virtual int compare(PyObject *other);
|
||||
|
||||
static IUnknown *GetI(PyObject *self);
|
||||
IUnknown *m_obj;
|
||||
static char *szErrMsgObjectReleased;
|
||||
static void SafeRelease(PyIUnknown *ob);
|
||||
static PyComTypeObject type;
|
||||
|
||||
// The Python methods
|
||||
static PyObject *QueryInterface(PyObject *self, PyObject *args);
|
||||
static PyObject *SafeRelease(PyObject *self, PyObject *args);
|
||||
|
||||
protected:
|
||||
PyIUnknown(IUnknown *punk);
|
||||
~PyIUnknown();
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// class PyIDispatch
|
||||
|
||||
class PYCOM_EXPORT PyIDispatch : public PyIUnknown
|
||||
{
|
||||
public:
|
||||
MAKE_PYCOM_CTOR(PyIDispatch);
|
||||
static IDispatch *GetI(PyObject *self);
|
||||
static PyComTypeObject type;
|
||||
|
||||
// The Python methods
|
||||
static PyObject *Invoke(PyObject *self, PyObject *args);
|
||||
static PyObject *InvokeTypes(PyObject *self, PyObject *args);
|
||||
static PyObject *GetIDsOfNames(PyObject *self, PyObject *args);
|
||||
static PyObject *GetTypeInfo(PyObject *self, PyObject *args);
|
||||
static PyObject *GetTypeInfoCount(PyObject *self, PyObject *args);
|
||||
protected:
|
||||
PyIDispatch(IUnknown *pdisp);
|
||||
~PyIDispatch();
|
||||
};
|
||||
|
||||
#ifndef NO_PYCOM_IDISPATCHEX
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// class PyIDispatchEx
|
||||
|
||||
class PYCOM_EXPORT PyIDispatchEx : public PyIDispatch
|
||||
{
|
||||
public:
|
||||
MAKE_PYCOM_CTOR_ERRORINFO(PyIDispatchEx, IID_IDispatchEx);
|
||||
static IDispatchEx *GetI(PyObject *self);
|
||||
static PyComTypeObject type;
|
||||
|
||||
// The Python methods
|
||||
static PyObject *GetDispID(PyObject *self, PyObject *args);
|
||||
static PyObject *InvokeEx(PyObject *self, PyObject *args);
|
||||
static PyObject *DeleteMemberByName(PyObject *self, PyObject *args);
|
||||
static PyObject *DeleteMemberByDispID(PyObject *self, PyObject *args);
|
||||
static PyObject *GetMemberProperties(PyObject *self, PyObject *args);
|
||||
static PyObject *GetMemberName(PyObject *self, PyObject *args);
|
||||
static PyObject *GetNextDispID(PyObject *self, PyObject *args);
|
||||
|
||||
protected:
|
||||
PyIDispatchEx(IUnknown *pdisp);
|
||||
~PyIDispatchEx();
|
||||
};
|
||||
#endif // NO_PYCOM_IDISPATCHEX
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// class PyIClassFactory
|
||||
|
||||
class PYCOM_EXPORT PyIClassFactory : public PyIUnknown
|
||||
{
|
||||
public:
|
||||
MAKE_PYCOM_CTOR(PyIClassFactory);
|
||||
static IClassFactory *GetI(PyObject *self);
|
||||
static PyComTypeObject type;
|
||||
|
||||
// The Python methods
|
||||
static PyObject *CreateInstance(PyObject *self, PyObject *args);
|
||||
static PyObject *LockServer(PyObject *self, PyObject *args);
|
||||
protected:
|
||||
PyIClassFactory(IUnknown *pdisp);
|
||||
~PyIClassFactory();
|
||||
};
|
||||
|
||||
#ifndef NO_PYCOM_IPROVIDECLASSINFO
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// class PyIProvideTypeInfo
|
||||
|
||||
class PYCOM_EXPORT PyIProvideClassInfo : public PyIUnknown
|
||||
{
|
||||
public:
|
||||
MAKE_PYCOM_CTOR(PyIProvideClassInfo);
|
||||
static IProvideClassInfo *GetI(PyObject *self);
|
||||
static PyComTypeObject type;
|
||||
|
||||
// The Python methods
|
||||
static PyObject *GetClassInfo(PyObject *self, PyObject *args);
|
||||
protected:
|
||||
PyIProvideClassInfo(IUnknown *pdisp);
|
||||
~PyIProvideClassInfo();
|
||||
};
|
||||
|
||||
class PYCOM_EXPORT PyIProvideClassInfo2 : public PyIProvideClassInfo
|
||||
{
|
||||
public:
|
||||
MAKE_PYCOM_CTOR(PyIProvideClassInfo2);
|
||||
static IProvideClassInfo2 *GetI(PyObject *self);
|
||||
static PyComTypeObject type;
|
||||
|
||||
// The Python methods
|
||||
static PyObject *GetGUID(PyObject *self, PyObject *args);
|
||||
protected:
|
||||
PyIProvideClassInfo2(IUnknown *pdisp);
|
||||
~PyIProvideClassInfo2();
|
||||
};
|
||||
#endif //NO_PYCOM_IPROVIDECLASSINFO
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// class PyITypeInfo
|
||||
class PYCOM_EXPORT PyITypeInfo : public PyIUnknown
|
||||
{
|
||||
public:
|
||||
MAKE_PYCOM_CTOR(PyITypeInfo);
|
||||
static PyComTypeObject type;
|
||||
static ITypeInfo *GetI(PyObject *self);
|
||||
|
||||
PyObject *GetContainingTypeLib();
|
||||
PyObject *GetDocumentation(MEMBERID);
|
||||
PyObject *GetRefTypeInfo(HREFTYPE href);
|
||||
PyObject *GetRefTypeOfImplType(int index);
|
||||
PyObject *GetFuncDesc(int pos);
|
||||
PyObject *GetIDsOfNames(OLECHAR FAR* FAR*, int);
|
||||
PyObject *GetNames(MEMBERID);
|
||||
PyObject *GetTypeAttr();
|
||||
PyObject *GetVarDesc(int pos);
|
||||
PyObject *GetImplTypeFlags(int index);
|
||||
PyObject *GetTypeComp();
|
||||
|
||||
protected:
|
||||
PyITypeInfo(IUnknown *);
|
||||
~PyITypeInfo();
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// class PyITypeComp
|
||||
class PYCOM_EXPORT PyITypeComp : public PyIUnknown
|
||||
{
|
||||
public:
|
||||
MAKE_PYCOM_CTOR(PyITypeComp);
|
||||
static PyComTypeObject type;
|
||||
static ITypeComp *GetI(PyObject *self);
|
||||
|
||||
PyObject *Bind(OLECHAR* szName, unsigned short wflags);
|
||||
PyObject *BindType(OLECHAR* szName);
|
||||
|
||||
protected:
|
||||
PyITypeComp(IUnknown *);
|
||||
~PyITypeComp();
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// class CPyTypeLib
|
||||
|
||||
class PYCOM_EXPORT PyITypeLib : public PyIUnknown
|
||||
{
|
||||
public:
|
||||
MAKE_PYCOM_CTOR(PyITypeLib);
|
||||
static PyComTypeObject type;
|
||||
static ITypeLib *GetI(PyObject *self);
|
||||
|
||||
PyObject *GetLibAttr();
|
||||
PyObject *GetDocumentation(int pos);
|
||||
PyObject *GetTypeInfo(int pos);
|
||||
PyObject *GetTypeInfoCount();
|
||||
PyObject *GetTypeInfoOfGuid(REFGUID guid);
|
||||
PyObject *GetTypeInfoType(int pos);
|
||||
PyObject *GetTypeComp();
|
||||
|
||||
protected:
|
||||
PyITypeLib(IUnknown *);
|
||||
~PyITypeLib();
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// class PyIConnectionPoint
|
||||
|
||||
class PYCOM_EXPORT PyIConnectionPoint : public PyIUnknown
|
||||
{
|
||||
public:
|
||||
MAKE_PYCOM_CTOR_ERRORINFO(PyIConnectionPoint,IID_IConnectionPoint);
|
||||
static PyComTypeObject type;
|
||||
static IConnectionPoint *GetI(PyObject *self);
|
||||
|
||||
static PyObject *GetConnectionInterface(PyObject *self, PyObject *args);
|
||||
static PyObject *GetConnectionPointContainer(PyObject *self, PyObject *args);
|
||||
static PyObject *Advise(PyObject *self, PyObject *args);
|
||||
static PyObject *Unadvise(PyObject *self, PyObject *args);
|
||||
static PyObject *EnumConnections(PyObject *self, PyObject *args);
|
||||
|
||||
protected:
|
||||
PyIConnectionPoint(IUnknown *);
|
||||
~PyIConnectionPoint();
|
||||
};
|
||||
|
||||
class PYCOM_EXPORT PyIConnectionPointContainer : public PyIUnknown
|
||||
{
|
||||
public:
|
||||
MAKE_PYCOM_CTOR_ERRORINFO(PyIConnectionPointContainer, IID_IConnectionPointContainer);
|
||||
static PyComTypeObject type;
|
||||
static IConnectionPointContainer *GetI(PyObject *self);
|
||||
|
||||
static PyObject *EnumConnectionPoints(PyObject *self, PyObject *args);
|
||||
static PyObject *FindConnectionPoint(PyObject *self, PyObject *args);
|
||||
|
||||
protected:
|
||||
PyIConnectionPointContainer(IUnknown *);
|
||||
~PyIConnectionPointContainer();
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// class PythonOleArgHelper
|
||||
//
|
||||
// A PythonOleArgHelper is used primarily to help out Python helpers
|
||||
// which need to convert from a Python object when the specific OLE
|
||||
// type is known - eg, when a TypeInfo is available.
|
||||
//
|
||||
// The type of conversion determines who owns what buffers etc. I wish BYREF didnt exist :-)
|
||||
typedef enum {
|
||||
// We dont know what sort of conversion it is yet.
|
||||
POAH_CONVERT_UNKNOWN,
|
||||
// A PyObject is given, we convert to a VARIANT, make the COM call, then BYREFs back to a PyObject
|
||||
// ie, this is typically a "normal" COM call, where Python initiates the call
|
||||
POAH_CONVERT_FROM_PYOBJECT,
|
||||
// A VARIANT is given, we convert to a PyObject, make the Python call, then BYREFs back to a VARIANT.
|
||||
// ie, this is typically handling a COM event, where COM itself initiates the call.
|
||||
POAH_CONVERT_FROM_VARIANT,
|
||||
} POAH_CONVERT_DIRECTION;
|
||||
|
||||
class PYCOM_EXPORT PythonOleArgHelper
|
||||
{
|
||||
public:
|
||||
PythonOleArgHelper();
|
||||
~PythonOleArgHelper();
|
||||
BOOL ParseTypeInformation(PyObject *reqdObjectTuple);
|
||||
|
||||
// Using this call with reqdObject != NULL will check the existing
|
||||
// VT_ of the variant. If not VT_EMPTY, then the result will be coerced to
|
||||
// that type. This contrasts with PyCom_PyObjectToVariant which just
|
||||
// uses the Python type to determine the variant type.
|
||||
BOOL MakeObjToVariant(PyObject *obj, VARIANT *var, PyObject *reqdObjectTuple = NULL);
|
||||
PyObject *MakeVariantToObj(VARIANT *var);
|
||||
|
||||
VARTYPE m_reqdType;
|
||||
BOOL m_bParsedTypeInfo;
|
||||
BOOL m_bIsOut;
|
||||
POAH_CONVERT_DIRECTION m_convertDirection;
|
||||
PyObject *m_pyVariant; // if non-null, a win32com.client.VARIANT
|
||||
union {
|
||||
void *m_pValueHolder;
|
||||
short m_sBuf;
|
||||
long m_lBuf;
|
||||
LONGLONG m_llBuf;
|
||||
VARIANT_BOOL m_boolBuf;
|
||||
double m_dBuf;
|
||||
float m_fBuf;
|
||||
IDispatch *m_dispBuf;
|
||||
IUnknown *m_unkBuf;
|
||||
SAFEARRAY *m_arrayBuf;
|
||||
VARIANT *m_varBuf;
|
||||
DATE m_dateBuf;
|
||||
CY m_cyBuf;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// global functions and variables
|
||||
PYCOM_EXPORT BOOL MakePythonArgumentTuples(PyObject **pArgs, PythonOleArgHelper **ppHelpers,
|
||||
PyObject **pNamedArgs, PythonOleArgHelper **ppNamedHelpers,
|
||||
DISPPARAMS FAR* params);
|
||||
|
||||
|
||||
// Convert a Python object to a BSTR - allow embedded NULLs, None, etc.
|
||||
PYCOM_EXPORT BOOL PyCom_BstrFromPyObject(PyObject *stringObject, BSTR *pResult, BOOL bNoneOK = FALSE);
|
||||
|
||||
// MakeBstrToObj - convert a BSTR into a Python string.
|
||||
//
|
||||
// ONLY USE THIS FOR TRUE BSTR's - Use the fn below for OLECHAR *'s.
|
||||
// NOTE - does not use standard macros, so NULLs get through!
|
||||
PYCOM_EXPORT PyObject *MakeBstrToObj(const BSTR bstr);
|
||||
|
||||
// Size info is available (eg, a fn returns a string and also fills in a size variable)
|
||||
PYCOM_EXPORT PyObject *MakeOLECHARToObj(const OLECHAR * str, int numChars);
|
||||
|
||||
// No size info avail.
|
||||
PYCOM_EXPORT PyObject *MakeOLECHARToObj(const OLECHAR * str);
|
||||
|
||||
PYCOM_EXPORT void PyCom_LogF(const char *fmt, ...);
|
||||
|
||||
// Generic conversion from python sequence to VT_VECTOR array
|
||||
// Resulting array must be freed with CoTaskMemFree
|
||||
template <typename arraytype>
|
||||
BOOL SeqToVector(PyObject *ob, arraytype **pA, ULONG *pcount, BOOL (*converter)(PyObject *, arraytype *)){
|
||||
TmpPyObject seq = PyWinSequence_Tuple(ob, pcount);
|
||||
if (seq == NULL)
|
||||
return FALSE;
|
||||
*pA = (arraytype *)CoTaskMemAlloc(*pcount * sizeof(arraytype));
|
||||
if (*pA == NULL){
|
||||
PyErr_NoMemory();
|
||||
return FALSE;
|
||||
}
|
||||
for (ULONG i=0; i<*pcount; i++){
|
||||
PyObject *item = PyTuple_GET_ITEM((PyObject *)seq, i);
|
||||
if (!(*converter)(item, &(*pA)[i]))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif // __PYTHONCOM_H__
|
||||
55
Lib/site-packages/win32com/include/PythonCOMRegister.h
Normal file
55
Lib/site-packages/win32com/include/PythonCOMRegister.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
// Support for PythonCOM and its extensions to register the interfaces,
|
||||
// gateways and IIDs it supports.
|
||||
//
|
||||
// The module can simply declare an array of type PyCom_InterfaceSupportInfo, then
|
||||
// use the macros to populate it.
|
||||
//
|
||||
// See Register.cpp and AXScript.cpp for examples on its use.
|
||||
|
||||
#ifndef __PYTHONCOMREGISTER_H__
|
||||
#define __PYTHONCOMREGISTER_H__
|
||||
|
||||
#include "PythonCOMServer.h" // Need defns in this file...
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const GUID *pGUID; // The supported IID - required
|
||||
const char *interfaceName; // Name of the interface - required
|
||||
const char *iidName; // Name of the IID that goes into the dict. - required
|
||||
PyTypeObject *pTypeOb; // the type object for client PyI* side - NULL for server only support.
|
||||
pfnPyGatewayConstructor ctor; // Gateway (PyG*) interface constructor - NULL for client only support
|
||||
|
||||
} PyCom_InterfaceSupportInfo;
|
||||
|
||||
#define PYCOM_INTERFACE_IID_ONLY(ifc) { &IID_I##ifc, "I" #ifc, "IID_I" #ifc, NULL, NULL }
|
||||
#define PYCOM_INTERFACE_CLSID_ONLY(ifc) { &CLSID_##ifc, "CLSID_" #ifc, "CLSID_" #ifc, NULL, NULL }
|
||||
#define PYCOM_INTERFACE_CATID_ONLY(ifc) { &CATID_##ifc, "CATID_" #ifc, "CATID_" #ifc, NULL, NULL }
|
||||
#define PYCOM_INTERFACE_CLIENT_ONLY(ifc) { &IID_I##ifc, "I" #ifc, "IID_I" #ifc, &PyI##ifc::type, NULL }
|
||||
#define PYCOM_INTERFACE_SERVER_ONLY(ifc) { &IID_I##ifc, "I" #ifc, "IID_I" #ifc, NULL, GET_PYGATEWAY_CTOR(PyG##ifc)}
|
||||
#define PYCOM_INTERFACE_FULL(ifc) { &IID_I##ifc, "I" #ifc, "IID_I" #ifc, &PyI##ifc::type, GET_PYGATEWAY_CTOR(PyG##ifc)}
|
||||
|
||||
// Versions that use __uuidof() to get the IID, which seems to avoid the need
|
||||
// to link with a lib holding the IIDs. Note that almost all extensions
|
||||
// build with __uuidof() being the default; the build failed at 'shell' - so
|
||||
// we could consider making this the default and making the 'explicit' version
|
||||
// above the special case.
|
||||
#define PYCOM_INTERFACE_IID_ONLY_UUIDOF(ifc) { &__uuidof(I##ifc), "I" #ifc, "IID_I" #ifc, NULL, NULL }
|
||||
#define PYCOM_INTERFACE_CLIENT_ONLY_UUIDOF(ifc) { &__uuidof(I##ifc), "I" #ifc, "IID_I" #ifc, &PyI##ifc::type, NULL }
|
||||
#define PYCOM_INTERFACE_SERVER_ONLY_UUIDOF(ifc) { &__uuidof(I##ifc), "I" #ifc, "IID_I" #ifc, NULL, GET_PYGATEWAY_CTOR(PyG##ifc)}
|
||||
#define PYCOM_INTERFACE_FULL_UUIDOF(ifc) { &__uuidof(I##ifc), "I" #ifc, "IID_I" #ifc, &PyI##ifc::type, GET_PYGATEWAY_CTOR(PyG##ifc)}
|
||||
|
||||
// Prototypes for the register functions
|
||||
|
||||
// Register a PythonCOM extension module
|
||||
PYCOM_EXPORT int PyCom_RegisterExtensionSupport( PyObject *dict, const PyCom_InterfaceSupportInfo *pInterfaces, int numEntries);
|
||||
|
||||
// THESE SHOULD NO LONGER BE USED. Instead, use the functions above passing an
|
||||
// array of PyCom_InterfaceSupportInfo objects.
|
||||
|
||||
PYCOM_EXPORT int PyCom_RegisterClientType(PyTypeObject *typeOb, const GUID *guid);
|
||||
|
||||
HRESULT PYCOM_EXPORT PyCom_RegisterGatewayObject(REFIID iid, pfnPyGatewayConstructor ctor, const char *interfaceName);
|
||||
PYCOM_EXPORT int PyCom_IsGatewayRegistered(REFIID iid);
|
||||
|
||||
|
||||
#endif /* __PYTHONCOMREGISTER_H__ */
|
||||
162
Lib/site-packages/win32com/include/PythonCOMServer.h
Normal file
162
Lib/site-packages/win32com/include/PythonCOMServer.h
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
#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__ */
|
||||
Loading…
Add table
Add a link
Reference in a new issue