First checkin of the Python XPCOM bindings.
git-svn-id: svn://10.0.0.236/trunk@87331 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
219
mozilla/extensions/python/xpcom/src/ErrorUtils.cpp
Normal file
219
mozilla/extensions/python/xpcom/src/ErrorUtils.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsFileStream.h>
|
||||
|
||||
static char *PyTraceback_AsString(PyObject *exc_tb);
|
||||
|
||||
// The internal helper that actually moves the
|
||||
// formatted string to the target!
|
||||
|
||||
void LogMessage(const char *prefix, const char *pszMessageText)
|
||||
{
|
||||
nsOutputConsoleStream console;
|
||||
console << prefix << pszMessageText;
|
||||
}
|
||||
|
||||
// A helper for the various logging routines.
|
||||
static void VLogF(const char *prefix, const char *fmt, va_list argptr)
|
||||
{
|
||||
char buff[512];
|
||||
|
||||
vsprintf(buff, fmt, argptr);
|
||||
|
||||
LogMessage(prefix, buff);
|
||||
}
|
||||
|
||||
void PyXPCOM_LogError(const char *fmt, ...)
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker, fmt);
|
||||
VLogF("PyXPCOM Error: ", fmt, marker);
|
||||
// If we have a Python exception, also log that:
|
||||
PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
|
||||
PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
|
||||
if (exc_typ) {
|
||||
PyErr_NormalizeException( &exc_typ, &exc_val, &exc_tb);
|
||||
char *string1 = nsnull;
|
||||
nsOutputStringStream streamout(string1);
|
||||
|
||||
if (exc_tb) {
|
||||
const char *szTraceback = PyTraceback_AsString(exc_tb);
|
||||
if (szTraceback == NULL)
|
||||
streamout << "Can't get the traceback info!";
|
||||
else {
|
||||
streamout << "Traceback (most recent call last):\n";
|
||||
streamout << szTraceback;
|
||||
PyMem_Free((ANY *)szTraceback);
|
||||
}
|
||||
}
|
||||
PyObject *temp = PyObject_Str(exc_typ);
|
||||
if (temp) {
|
||||
streamout << PyString_AsString(temp);
|
||||
Py_DECREF(temp);
|
||||
} else
|
||||
streamout << "Can't convert exception to a string!";
|
||||
streamout << ": ";
|
||||
if (exc_val != NULL) {
|
||||
temp = PyObject_Str(exc_val);
|
||||
if (temp) {
|
||||
streamout << PyString_AsString(temp);
|
||||
Py_DECREF(temp);
|
||||
} else
|
||||
streamout << "Can't convert exception value to a string!";
|
||||
}
|
||||
streamout << "\n";
|
||||
LogMessage("PyXPCOM Exception:", string1);
|
||||
}
|
||||
PyErr_Restore(exc_typ, exc_val, exc_tb);
|
||||
}
|
||||
|
||||
void PyXPCOM_LogWarning(const char *fmt, ...)
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker, fmt);
|
||||
VLogF("PyXPCOM Warning: ", fmt, marker);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void PyXPCOM_LogDebug(const char *fmt, ...)
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker, fmt);
|
||||
VLogF("PyXPCOM Debug: ", fmt, marker);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
PyObject *PyXPCOM_BuildPyException(nsresult r)
|
||||
{
|
||||
// Need the message etc.
|
||||
PyObject *evalue = Py_BuildValue("i", r);
|
||||
PyErr_SetObject(PyXPCOM_Error, evalue);
|
||||
Py_XDECREF(evalue);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nsresult PyXPCOM_SetCOMErrorFromPyException()
|
||||
{
|
||||
if (!PyErr_Occurred())
|
||||
// No error occurred
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* Obtains a string from a Python traceback.
|
||||
This is the exact same string as "traceback.print_exc" would return.
|
||||
|
||||
Pass in a Python traceback object (probably obtained from PyErr_Fetch())
|
||||
Result is a string which must be free'd using PyMem_Free()
|
||||
*/
|
||||
#define TRACEBACK_FETCH_ERROR(what) {errMsg = what; goto done;}
|
||||
|
||||
char *PyTraceback_AsString(PyObject *exc_tb)
|
||||
{
|
||||
char *errMsg = NULL; /* a static that hold a local error message */
|
||||
char *result = NULL; /* a valid, allocated result. */
|
||||
PyObject *modStringIO = NULL;
|
||||
PyObject *modTB = NULL;
|
||||
PyObject *obFuncStringIO = NULL;
|
||||
PyObject *obStringIO = NULL;
|
||||
PyObject *obFuncTB = NULL;
|
||||
PyObject *argsTB = NULL;
|
||||
PyObject *obResult = NULL;
|
||||
|
||||
/* Import the modules we need - cStringIO and traceback */
|
||||
modStringIO = PyImport_ImportModule("cStringIO");
|
||||
if (modStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant import cStringIO\n");
|
||||
|
||||
modTB = PyImport_ImportModule("traceback");
|
||||
if (modTB==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant import traceback\n");
|
||||
/* Construct a cStringIO object */
|
||||
obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO");
|
||||
if (obFuncStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant find cStringIO.StringIO\n");
|
||||
obStringIO = PyObject_CallObject(obFuncStringIO, NULL);
|
||||
if (obStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cStringIO.StringIO() failed\n");
|
||||
/* Get the traceback.print_exception function, and call it. */
|
||||
obFuncTB = PyObject_GetAttrString(modTB, "print_tb");
|
||||
if (obFuncTB==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant find traceback.print_tb\n");
|
||||
|
||||
argsTB = Py_BuildValue("OOO",
|
||||
exc_tb ? exc_tb : Py_None,
|
||||
Py_None,
|
||||
obStringIO);
|
||||
if (argsTB==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant make print_tb arguments\n");
|
||||
|
||||
obResult = PyObject_CallObject(obFuncTB, argsTB);
|
||||
if (obResult==NULL)
|
||||
TRACEBACK_FETCH_ERROR("traceback.print_tb() failed\n");
|
||||
/* Now call the getvalue() method in the StringIO instance */
|
||||
Py_DECREF(obFuncStringIO);
|
||||
obFuncStringIO = PyObject_GetAttrString(obStringIO, "getvalue");
|
||||
if (obFuncStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant find getvalue function\n");
|
||||
Py_DECREF(obResult);
|
||||
obResult = PyObject_CallObject(obFuncStringIO, NULL);
|
||||
if (obResult==NULL)
|
||||
TRACEBACK_FETCH_ERROR("getvalue() failed.\n");
|
||||
|
||||
/* And it should be a string all ready to go - duplicate it. */
|
||||
if (!PyString_Check(obResult))
|
||||
TRACEBACK_FETCH_ERROR("getvalue() did not return a string\n");
|
||||
|
||||
{ // a temp scope so I can use temp locals.
|
||||
char *tempResult = PyString_AsString(obResult);
|
||||
result = (char *)PyMem_Malloc(strlen(tempResult)+1);
|
||||
if (result==NULL)
|
||||
TRACEBACK_FETCH_ERROR("memory error duplicating the traceback string");
|
||||
|
||||
strcpy(result, tempResult);
|
||||
} // end of temp scope.
|
||||
done:
|
||||
/* All finished - first see if we encountered an error */
|
||||
if (result==NULL && errMsg != NULL) {
|
||||
result = (char *)PyMem_Malloc(strlen(errMsg)+1);
|
||||
if (result != NULL)
|
||||
/* if it does, not much we can do! */
|
||||
strcpy(result, errMsg);
|
||||
}
|
||||
Py_XDECREF(modStringIO);
|
||||
Py_XDECREF(modTB);
|
||||
Py_XDECREF(obFuncStringIO);
|
||||
Py_XDECREF(obStringIO);
|
||||
Py_XDECREF(obFuncTB);
|
||||
Py_XDECREF(argsTB);
|
||||
Py_XDECREF(obResult);
|
||||
return result;
|
||||
}
|
||||
|
||||
// See comments in PyXPCOM.h for why we need this!
|
||||
void PyXPCOM_MakePendingCalls()
|
||||
{
|
||||
while (1) {
|
||||
int rc = Py_MakePendingCalls();
|
||||
if (rc == 0)
|
||||
break;
|
||||
// An exception - just report it as normal.
|
||||
// Note that a traceback is very unlikely!
|
||||
PyXPCOM_LogError("Unhandled exception detected before entering Python.\n");
|
||||
PyErr_Clear();
|
||||
// And loop around again until we are told everything is done!
|
||||
}
|
||||
}
|
||||
757
mozilla/extensions/python/xpcom/src/PyGBase.cpp
Normal file
757
mozilla/extensions/python/xpcom/src/PyGBase.cpp
Normal file
@@ -0,0 +1,757 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// PyGBase.cpp - implementation of the PyG_Base class
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIModule.h>
|
||||
#include <nsIComponentLoader.h>
|
||||
#include <nsIInputStream.h>
|
||||
|
||||
static PRInt32 cGateways = 0;
|
||||
PRInt32 _PyXPCOM_GetGatewayCount(void)
|
||||
{
|
||||
return cGateways;
|
||||
}
|
||||
|
||||
extern PyG_Base *MakePyG_nsIModule(PyObject *);
|
||||
extern PyG_Base *MakePyG_nsIComponentLoader(PyObject *instance);
|
||||
extern PyG_Base *MakePyG_nsIInputStream(PyObject *instance);
|
||||
|
||||
static char *PyXPCOM_szDefaultGatewayAttributeName = "_com_instance_default_gateway_";
|
||||
nsresult GetDefaultGateway(PyObject *instance, REFNSIID iid, void **ret);
|
||||
void AddDefaultGateway(PyObject *instance, nsISupports *gateway);
|
||||
PRBool CheckDefaultGateway(PyObject *real_inst, REFNSIID iid, nsISupports **ret_gateway);
|
||||
|
||||
/*static*/ nsresult
|
||||
PyG_Base::CreateNew(PyObject *pPyInstance, const nsIID &iid, void **ppResult)
|
||||
{
|
||||
NS_PRECONDITION(ppResult && *ppResult==NULL, "NULL or uninitialized pointer");
|
||||
if (ppResult==nsnull)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PyG_Base *ret;
|
||||
// Hack for few extra gateways we support.
|
||||
if (iid.Equals(NS_GET_IID(nsIModule)))
|
||||
ret = MakePyG_nsIModule(pPyInstance);
|
||||
else if (iid.Equals(NS_GET_IID(nsIComponentLoader)))
|
||||
ret = MakePyG_nsIComponentLoader(pPyInstance);
|
||||
else if (iid.Equals(NS_GET_IID(nsIInputStream)))
|
||||
ret = MakePyG_nsIInputStream(pPyInstance);
|
||||
else
|
||||
ret = new PyXPCOM_XPTStub(pPyInstance, iid);
|
||||
if (ret==nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
ret->AddRef(); // The first reference for the caller.
|
||||
*ppResult = ret->ThisAsIID(iid);
|
||||
NS_ABORT_IF_FALSE(*ppResult != NULL, "ThisAsIID() gave NULL, but we know it supports it!");
|
||||
return *ppResult ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PyG_Base::PyG_Base(PyObject *instance, const nsIID &iid)
|
||||
{
|
||||
// Note that "instance" is the _policy_ instance!!
|
||||
NS_INIT_REFCNT();
|
||||
PR_AtomicIncrement(&cGateways);
|
||||
m_pBaseObject = NULL;
|
||||
// m_pWeakRef is an nsCOMPtr and needs no init.
|
||||
m_iid = iid;
|
||||
m_pPyObject = instance;
|
||||
NS_PRECONDITION(instance, "NULL PyObject for PyXPCOM_XPTStub!");
|
||||
#ifdef DEBUG_LIFETIMES
|
||||
{
|
||||
char *iid_repr;
|
||||
nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
|
||||
if (iim!=nsnull)
|
||||
iim->GetNameForIID(&iid, &iid_repr);
|
||||
PyObject *real_instance = PyObject_GetAttrString(instance, "_obj_");
|
||||
PyObject *real_repr = PyObject_Repr(real_instance);
|
||||
|
||||
PYXPCOM_LOG_DEBUG("PyG_Base created at %p\n instance_repr=%s\n IID=%s\n", this, PyString_AsString(real_repr), iid_repr);
|
||||
nsAllocator::Free(iid_repr);
|
||||
Py_XDECREF(real_instance);
|
||||
Py_XDECREF(real_repr);
|
||||
}
|
||||
#endif // DEBUG_LIFETIMES
|
||||
Py_XINCREF(instance); // instance should never be NULL - but whats an X between friends!
|
||||
|
||||
PyXPCOM_DLLAddRef();
|
||||
|
||||
#ifdef DEBUG_FULL
|
||||
LogF("PyGatewayBase: created %s", m_pPyObject ? m_pPyObject->ob_type->tp_name : "<NULL>");
|
||||
#endif
|
||||
}
|
||||
|
||||
PyG_Base::~PyG_Base()
|
||||
{
|
||||
PR_AtomicDecrement(&cGateways);
|
||||
#ifdef DEBUG_LIFETIMES
|
||||
PYXPCOM_LOG_DEBUG("PyG_Base: deleted %p", this);
|
||||
#endif
|
||||
if ( m_pPyObject ) {
|
||||
CEnterLeavePython celp;
|
||||
Py_DECREF(m_pPyObject);
|
||||
}
|
||||
if (m_pBaseObject)
|
||||
m_pBaseObject->Release();
|
||||
if (m_pWeakRef) {
|
||||
// Need to ensure some other thread isnt doing a QueryReferent on
|
||||
// our weak reference at the same time
|
||||
CEnterLeaveXPCOMFramework _celf;
|
||||
PyXPCOM_GatewayWeakReference *p = (PyXPCOM_GatewayWeakReference *)(nsISupports *)m_pWeakRef;
|
||||
p->m_pBase = nsnull;
|
||||
m_pWeakRef = nsnull;
|
||||
}
|
||||
PyXPCOM_DLLRelease();
|
||||
}
|
||||
|
||||
// Get the correct interface pointer for this object given the IID.
|
||||
void *PyG_Base::ThisAsIID( const nsIID &iid )
|
||||
{
|
||||
if (this==NULL) return NULL;
|
||||
if (iid.Equals(NS_GET_IID(nsISupports)))
|
||||
return (nsISupports *)(nsIInternalPython *)this;
|
||||
if (iid.Equals(NS_GET_IID(nsISupportsWeakReference)))
|
||||
return (nsISupportsWeakReference *)this;
|
||||
if (iid.Equals(NS_GET_IID(nsIInternalPython)))
|
||||
return (nsISupports *)(nsIInternalPython *)this;
|
||||
return NULL;
|
||||
};
|
||||
|
||||
// Call back into Python, passing a Python instance, and get back
|
||||
// an interface object that wraps the instance.
|
||||
/*static*/ PRBool
|
||||
PyG_Base::AutoWrapPythonInstance(PyObject *ob, const nsIID &iid, nsISupports **ppret)
|
||||
{
|
||||
NS_PRECONDITION(ppret!=NULL, "null pointer when wrapping a Python instance!");
|
||||
NS_PRECONDITION(ob && PyInstance_Check(ob), "AutoWrapPythonInstance is expecting an non-NULL instance!");
|
||||
PRBool ok = PR_FALSE;
|
||||
// XXX - todo - this static object leaks! (but Python on Windows leaks 2000+ objects as it is ;-)
|
||||
static PyObject *func = NULL; // fetch this once and remember!
|
||||
PyObject *obIID = NULL;
|
||||
PyObject *wrap_ret = NULL;
|
||||
PyObject *args = NULL;
|
||||
if (func==NULL) { // not thread-safe, but nothing bad can happen, except an extra reference leak
|
||||
PyObject *mod = PyImport_ImportModule("xpcom.server");
|
||||
if (mod)
|
||||
func = PyObject_GetAttrString(mod, "WrapObject");
|
||||
Py_XDECREF(mod);
|
||||
if (func==NULL) goto done;
|
||||
}
|
||||
// See if the instance has previously been wrapped.
|
||||
if (CheckDefaultGateway(ob, iid, ppret)) {
|
||||
ok = PR_TRUE; // life is good!
|
||||
} else {
|
||||
PyErr_Clear();
|
||||
|
||||
obIID = Py_nsIID::PyObjectFromIID(iid);
|
||||
if (obIID==NULL) goto done;
|
||||
args = Py_BuildValue("OO", ob, obIID);
|
||||
if (args==NULL) goto done;
|
||||
wrap_ret = PyEval_CallObject(func, args);
|
||||
if (wrap_ret==NULL) goto done;
|
||||
ok = Py_nsISupports::InterfaceFromPyObject(wrap_ret, iid, ppret, PR_FALSE, PR_FALSE);
|
||||
#ifdef DEBUG
|
||||
if (ok)
|
||||
// Check we _now_ have a default gateway
|
||||
{
|
||||
nsISupports *temp = NULL;
|
||||
NS_ABORT_IF_FALSE(CheckDefaultGateway(ob, iid, &temp), "Auto-wrapped object didnt get a default gateway!");
|
||||
if (temp) temp->Release();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
done:
|
||||
// Py_XDECREF(func); -- func is static for performance reasons.
|
||||
Py_XDECREF(obIID);
|
||||
Py_XDECREF(wrap_ret);
|
||||
Py_XDECREF(args);
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Call back into Python, passing a raw nsIInterface object, getting back
|
||||
// the object to actually use as the gateway parameter for this interface.
|
||||
// For example, it is expected that the policy will wrap the interface
|
||||
// object in one of the xpcom.client.Interface objects, allowing
|
||||
// natural usage of the interface from Python clients.
|
||||
// Note that piid will usually be NULL - this is because the runtime
|
||||
// reflection interfaces dont provide this information to me.
|
||||
// In this case, the Python code may choose to lookup the complete
|
||||
// interface info to obtain the IID.
|
||||
// It is expected (but should not be assumed) that the method info
|
||||
// or the IID will be NULL.
|
||||
// Worst case, the code should provide a wrapper for the nsiSupports interface,
|
||||
// so at least the user can simply QI the object.
|
||||
PyObject *
|
||||
PyG_Base::MakeInterfaceParam(nsISupports *pis,
|
||||
const nsIID *piid,
|
||||
int methodIndex /* = -1 */,
|
||||
const XPTParamDescriptor *d /* = NULL */,
|
||||
int paramIndex /* = -1 */)
|
||||
{
|
||||
if (pis==NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
// This condition is true today, but not necessarily so.
|
||||
// But if it ever triggers, the poor Python code has no real hope
|
||||
// of returning something useful, so we should at least do our
|
||||
// best to provide the useful data.
|
||||
NS_WARN_IF_FALSE( ((piid != NULL) ^ (d != NULL)) == 1, "No information on the interface available - Python's gunna have a hard time doing much with it!");
|
||||
PyObject *obIID = NULL;
|
||||
PyObject *obISupports = NULL;
|
||||
PyObject *obParamDesc = NULL;
|
||||
PyObject *result = NULL;
|
||||
|
||||
// get the basic interface first, as if we fail, we can try and use this.
|
||||
nsIID iid_check = piid ? *piid : NS_GET_IID(nsISupports);
|
||||
obISupports = Py_nsISupports::PyObjectFromInterface(pis, iid_check, PR_TRUE, PR_FALSE);
|
||||
if (!obISupports)
|
||||
goto done;
|
||||
if (piid==NULL) {
|
||||
obIID = Py_None;
|
||||
Py_INCREF(Py_None);
|
||||
} else
|
||||
obIID = Py_nsIID::PyObjectFromIID(*piid);
|
||||
if (obIID==NULL)
|
||||
goto done;
|
||||
obParamDesc = PyObject_FromXPTParamDescriptor(d);
|
||||
if (obParamDesc==NULL)
|
||||
goto done;
|
||||
|
||||
result = PyObject_CallMethod(m_pPyObject,
|
||||
"_MakeInterfaceParam_",
|
||||
"OOiOi",
|
||||
obISupports,
|
||||
obIID,
|
||||
methodIndex,
|
||||
obParamDesc,
|
||||
paramIndex);
|
||||
done:
|
||||
if (PyErr_Occurred()) {
|
||||
NS_WARN_IF_FALSE(result==NULL, "Have an error, but also a result!");
|
||||
PyXPCOM_LogError("Wrapping an interface object for the gateway failed\n");
|
||||
}
|
||||
Py_XDECREF(obIID);
|
||||
Py_XDECREF(obParamDesc);
|
||||
if (result==NULL) // we had an error.
|
||||
// return our obISupports. If NULL, we are really hosed and nothing we can do.
|
||||
return obISupports;
|
||||
// Dont need to return this - we have a better result.
|
||||
Py_XDECREF(obISupports);
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_Base::QueryInterface(REFNSIID iid, void** ppv)
|
||||
{
|
||||
#ifdef PYXPCOM_DEBUG_FULL
|
||||
{
|
||||
char *sziid = iid.ToString();
|
||||
LogF("PyGatewayBase::QueryInterface: %s", sziid);
|
||||
Allocator::Free(sziid);
|
||||
}
|
||||
#endif
|
||||
NS_PRECONDITION(ppv, "NULL pointer");
|
||||
if (ppv==nsnull)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*ppv = nsnull;
|
||||
// If one of our native interfaces (but NOT nsISupports if we have a base)
|
||||
// return this.
|
||||
// It is important is that nsISupports come from the base object
|
||||
// to ensure that we live by XPCOM identity rules (other interfaces need
|
||||
// not abide by this rule - only nsISupports.)
|
||||
if ( (m_pBaseObject==NULL || !iid.Equals(NS_GET_IID(nsISupports)))
|
||||
&& (*ppv=ThisAsIID(iid)) != NULL ) {
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
// If we have a "base object", then we need to delegate _every_ remaining
|
||||
// QI to it.
|
||||
if (m_pBaseObject != NULL && (m_pBaseObject->QueryInterface(iid, ppv)==NS_OK))
|
||||
return NS_OK;
|
||||
|
||||
// Call the Python policy to see if it (says it) supports the interface
|
||||
PRBool supports = PR_FALSE;
|
||||
{ // temp scope for Python lock
|
||||
CEnterLeavePython celp;
|
||||
|
||||
PyObject * ob = Py_nsIID::PyObjectFromIID(iid);
|
||||
PyObject * this_interface_ob = Py_nsISupports::PyObjectFromInterface((nsIInternalPython *)this, NS_GET_IID(nsISupports), PR_TRUE, PR_FALSE);
|
||||
if ( !ob || !this_interface_ob) {
|
||||
Py_XDECREF(ob);
|
||||
Py_XDECREF(this_interface_ob);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
PyObject *result = PyObject_CallMethod(m_pPyObject, "_QueryInterface_",
|
||||
"OO",
|
||||
this_interface_ob, ob);
|
||||
Py_DECREF(ob);
|
||||
Py_DECREF(this_interface_ob);
|
||||
|
||||
if ( result ) {
|
||||
if (Py_nsISupports::InterfaceFromPyObject(result, iid, (nsISupports **)ppv, PR_TRUE)) {
|
||||
// If OK, but NULL, _QI_ returned None, which simply means
|
||||
// "no such interface"
|
||||
supports = (*ppv!=NULL);
|
||||
// result has been QI'd and AddRef'd all ready for return.
|
||||
} else {
|
||||
// Dump this message and any Python exception before
|
||||
// reporting the fact that QI failed - this error
|
||||
// may provide clues!
|
||||
PyXPCOM_LogError("The _QueryInterface_ method returned an object of type '%s', but an interface was expected\n", result->ob_type->tp_name);
|
||||
// supports remains false
|
||||
}
|
||||
Py_DECREF(result);
|
||||
} else {
|
||||
NS_ABORT_IF_FALSE(PyErr_Occurred(), "Got NULL result, but no Python error flagged!");
|
||||
NS_WARN_IF_FALSE(!supports, "Have failure with success flag set!");
|
||||
PyXPCOM_LogError("The _QueryInterface_ processing failed.\n");
|
||||
// supports remains false.
|
||||
// We have reported the error, and are returning to COM,
|
||||
// so we should clear it.
|
||||
PyErr_Clear();
|
||||
}
|
||||
} // end of temp scope for Python lock - lock released here!
|
||||
if ( !supports )
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
|
||||
// Now setup the base object pointer back to me.
|
||||
// We do a QI on our internal one to ensure we can safely cast
|
||||
// the result to a PyG_Base (both from the POV that is may not
|
||||
// be a Python object, and that the vtables offsets may screw
|
||||
// us even if it is!)
|
||||
nsISupports *pLook = (nsISupports *)(*ppv);
|
||||
nsIInternalPython *pTemp;
|
||||
if (pLook->QueryInterface(NS_GET_IID(nsIInternalPython), (void **)&pTemp)==NS_OK) {
|
||||
// One of our objects, so set the base object if it doesnt already have one
|
||||
PyG_Base *pG = (PyG_Base *)pTemp;
|
||||
// Eeek - just these few next lines need to be thread-safe :-(
|
||||
CEnterLeaveXPCOMFramework _celf;
|
||||
if (pG->m_pBaseObject==NULL && pG != (PyG_Base *)this) {
|
||||
pG->m_pBaseObject = this;
|
||||
pG->m_pBaseObject->AddRef();
|
||||
#ifdef DEBUG_LIFETIMES
|
||||
PYXPCOM_LOG_DEBUG("PyG_Base setting BaseObject of %p to %p\n", pG, this);
|
||||
#endif
|
||||
}
|
||||
pTemp->Release();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsrefcnt
|
||||
PyG_Base::AddRef(void)
|
||||
{
|
||||
nsrefcnt cnt = (nsrefcnt) PR_AtomicIncrement((PRInt32*)&mRefCnt);
|
||||
NS_LOG_ADDREF(this, cnt, "PyG_Base", sizeof(*this));
|
||||
return cnt;
|
||||
}
|
||||
|
||||
nsrefcnt
|
||||
PyG_Base::Release(void)
|
||||
{
|
||||
nsrefcnt cnt = (nsrefcnt) PR_AtomicDecrement((PRInt32*)&mRefCnt);
|
||||
NS_LOG_RELEASE(this, cnt, "PyG_Base");
|
||||
if ( cnt == 0 )
|
||||
delete this;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_Base::GetWeakReference(nsIWeakReference **ret)
|
||||
{
|
||||
NS_PRECONDITION(ret, "null pointer");
|
||||
if (ret==nsnull) return NS_ERROR_INVALID_POINTER;
|
||||
if (!m_pWeakRef) {
|
||||
// First query for a weak reference - create it.
|
||||
m_pWeakRef = new PyXPCOM_GatewayWeakReference(this);
|
||||
NS_ABORT_IF_FALSE(m_pWeakRef, "Shouldn't be able to fail creating a weak reference!");
|
||||
if (!m_pWeakRef)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
*ret = m_pWeakRef;
|
||||
(*ret)->AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult PyG_Base::HandleNativeGatewayError(const char *szMethodName)
|
||||
{
|
||||
nsresult rc = NS_OK;
|
||||
if (PyErr_Occurred()) {
|
||||
// The error handling - fairly involved, but worth it as
|
||||
// good error reporting is critical for users to know WTF
|
||||
// is going on - especially with TypeErrors etc in their
|
||||
// return values (ie, after the Python code has successfully
|
||||
// existed, but we encountered errors unpacking their
|
||||
// result values for the COM caller - there is literally no
|
||||
// way to catch these exceptions from Python code, as their
|
||||
// is no Python function on the call-stack)
|
||||
|
||||
// First line of attack in an error is to call-back on the policy.
|
||||
// If the callback of the error handler succeeds and returns an
|
||||
// integer (for the nsresult), we take no further action.
|
||||
|
||||
// If this callback fails, we log _2_ exceptions - the error handler
|
||||
// error, and the original error.
|
||||
|
||||
PRBool bProcessMainError = PR_TRUE; // set to false if our exception handler does its thing!
|
||||
PyObject *exc_typ, *exc_val, *exc_tb;
|
||||
PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
|
||||
|
||||
PyObject *err_result = PyObject_CallMethod(m_pPyObject,
|
||||
"_GatewayException_",
|
||||
"z(OOO)",
|
||||
szMethodName,
|
||||
exc_typ ? exc_typ : Py_None, // should never be NULL, but defensive programming...
|
||||
exc_val ? exc_val : Py_None, // may well be NULL.
|
||||
exc_tb ? exc_tb : Py_None); // may well be NULL.
|
||||
if (err_result == NULL) {
|
||||
PyXPCOM_LogError("The exception handler _CallMethodException_ failed!\n");
|
||||
} else if (err_result == Py_None) {
|
||||
// The exception handler has chosen not to do anything with
|
||||
// this error, so we still need to print it!
|
||||
;
|
||||
} else if (PyInt_Check(err_result)) {
|
||||
// The exception handler has given us the nresult.
|
||||
rc = PyInt_AsLong(err_result);
|
||||
bProcessMainError = PR_FALSE;
|
||||
} else {
|
||||
// The exception handler succeeded, but returned other than
|
||||
// int or None.
|
||||
PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", err_result->ob_type->tp_name);
|
||||
}
|
||||
Py_XDECREF(err_result);
|
||||
PyErr_Restore(exc_typ, exc_val, exc_tb);
|
||||
if (bProcessMainError) {
|
||||
PyXPCOM_LogError("The function '%s' failed\n", szMethodName);
|
||||
rc = PyXPCOM_SetCOMErrorFromPyException();
|
||||
}
|
||||
PyErr_Clear();
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static nsresult do_dispatch(
|
||||
PyObject *pPyObject,
|
||||
PyObject **ppResult,
|
||||
const char *szMethodName,
|
||||
const char *szFormat,
|
||||
va_list va
|
||||
)
|
||||
{
|
||||
NS_PRECONDITION(ppResult, "Must provide a result buffer");
|
||||
*ppResult = nsnull;
|
||||
// Build the Invoke arguments...
|
||||
PyObject *args = NULL;
|
||||
PyObject *method = NULL;
|
||||
PyObject *real_ob = NULL;
|
||||
nsresult ret = NS_ERROR_FAILURE;
|
||||
if ( szFormat )
|
||||
args = Py_VaBuildValue((char *)szFormat, va);
|
||||
else
|
||||
args = PyTuple_New(0);
|
||||
if ( !args )
|
||||
goto done;
|
||||
|
||||
// make sure a tuple.
|
||||
if ( !PyTuple_Check(args) ) {
|
||||
PyObject *a = PyTuple_New(1);
|
||||
if ( a == NULL )
|
||||
{
|
||||
Py_DECREF(args);
|
||||
goto done;
|
||||
}
|
||||
PyTuple_SET_ITEM(a, 0, args);
|
||||
args = a;
|
||||
}
|
||||
// Bit to a hack here to maintain the use of a policy.
|
||||
// We actually get the policies underlying object
|
||||
// to make the call on.
|
||||
real_ob = PyObject_GetAttrString(pPyObject, "_obj_");
|
||||
if (real_ob == NULL) {
|
||||
PyErr_Format(PyExc_AttributeError, "The policy object does not have an '_obj_' attribute.");
|
||||
goto done;
|
||||
}
|
||||
method = PyObject_GetAttrString(real_ob, (char *)szMethodName);
|
||||
if ( !method ) {
|
||||
PyErr_Clear();
|
||||
ret = NS_COMFALSE;
|
||||
goto done;
|
||||
}
|
||||
// Make the call
|
||||
*ppResult = PyEval_CallObject(method, args);
|
||||
ret = *ppResult ? NS_OK : NS_ERROR_FAILURE;
|
||||
done:
|
||||
Py_XDECREF(method);
|
||||
Py_XDECREF(real_ob);
|
||||
Py_XDECREF(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
nsresult PyG_Base::InvokeNativeViaPolicyInternal(
|
||||
const char *szMethodName,
|
||||
PyObject **ppResult,
|
||||
const char *szFormat,
|
||||
va_list va
|
||||
)
|
||||
{
|
||||
if ( m_pPyObject == NULL || szMethodName == NULL )
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PyObject *temp = nsnull;
|
||||
if (ppResult == nsnull)
|
||||
ppResult = &temp;
|
||||
nsresult nr = do_dispatch(m_pPyObject, ppResult, szMethodName, szFormat, va);
|
||||
|
||||
// If temp is NULL, they provided a buffer, and we dont touch it.
|
||||
// If not NULL, *ppResult = temp, and _we_ do own it.
|
||||
Py_XDECREF(temp);
|
||||
return nr;
|
||||
}
|
||||
|
||||
nsresult PyG_Base::InvokeNativeViaPolicy(
|
||||
const char *szMethodName,
|
||||
PyObject **ppResult /* = NULL */,
|
||||
const char *szFormat /* = NULL */,
|
||||
...
|
||||
)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, szFormat);
|
||||
nsresult nr = InvokeNativeViaPolicyInternal(szMethodName, ppResult, szFormat, va);
|
||||
va_end(va);
|
||||
|
||||
if (nr==NS_COMFALSE) {
|
||||
// Only problem was missing method.
|
||||
PyErr_Format(PyExc_AttributeError, "The object does not have a '%s' function.", szMethodName);
|
||||
}
|
||||
return nr == NS_OK ? NS_OK : HandleNativeGatewayError(szMethodName);
|
||||
}
|
||||
|
||||
nsresult PyG_Base::InvokeNativeGetViaPolicy(
|
||||
const char *szPropertyName,
|
||||
PyObject **ppResult /* = NULL */
|
||||
)
|
||||
{
|
||||
PyObject *ob_ret = NULL;
|
||||
nsresult ret = NS_OK;
|
||||
PyObject *real_ob = NULL;
|
||||
if ( m_pPyObject == NULL || szPropertyName == NULL )
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
// First see if we have a method of that name.
|
||||
char buf[256];
|
||||
strcpy(buf, "get_");
|
||||
strncat(buf, szPropertyName, sizeof(buf)*sizeof(buf[0])-strlen(buf)-1);
|
||||
buf[sizeof(buf)/sizeof(buf[0])-1] = '\0';
|
||||
ret = InvokeNativeViaPolicyInternal(buf, ppResult, nsnull, nsnull);
|
||||
if (ret == NS_COMFALSE) {
|
||||
// No method of that name - just try a property.
|
||||
// Bit to a hack here to maintain the use of a policy.
|
||||
// We actually get the policies underlying object
|
||||
// to make the call on.
|
||||
real_ob = PyObject_GetAttrString(m_pPyObject, "_obj_");
|
||||
if (real_ob == NULL) {
|
||||
PyErr_Format(PyExc_AttributeError, "The policy object does not have an '_obj_' attribute.");
|
||||
ret = HandleNativeGatewayError(szPropertyName);
|
||||
goto done;
|
||||
}
|
||||
ob_ret = PyObject_GetAttrString(real_ob, (char *)szPropertyName);
|
||||
if (ob_ret==NULL) {
|
||||
PyErr_Format(PyExc_AttributeError,
|
||||
"The object does not have a 'get_%s' function, or a '%s attribute.",
|
||||
szPropertyName, szPropertyName);
|
||||
} else {
|
||||
ret = NS_OK;
|
||||
if (ppResult)
|
||||
*ppResult = ob_ret;
|
||||
else
|
||||
Py_XDECREF(ob_ret);
|
||||
}
|
||||
}
|
||||
if (ret != NS_OK)
|
||||
ret = HandleNativeGatewayError(szPropertyName);
|
||||
|
||||
done:
|
||||
Py_XDECREF(real_ob);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nsresult PyG_Base::InvokeNativeSetViaPolicy(
|
||||
const char *szPropertyName,
|
||||
...
|
||||
)
|
||||
{
|
||||
if ( m_pPyObject == NULL || szPropertyName == NULL )
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
PyObject *ob_ret = NULL;
|
||||
nsresult ret = NS_OK;
|
||||
PyObject *real_ob = NULL;
|
||||
char buf[256];
|
||||
strcpy(buf, "set_");
|
||||
strncat(buf, szPropertyName, sizeof(buf)*sizeof(buf[0])-strlen(buf)-1);
|
||||
buf[sizeof(buf)/sizeof(buf[0])-1] = '\0';
|
||||
va_list va;
|
||||
va_start(va, szPropertyName);
|
||||
ret = InvokeNativeViaPolicyInternal(buf, NULL, "O", va);
|
||||
va_end(va);
|
||||
if (ret == NS_COMFALSE) {
|
||||
// No method of that name - just try a property.
|
||||
// Bit to a hack here to maintain the use of a policy.
|
||||
// We actually get the policies underlying object
|
||||
// to make the call on.
|
||||
real_ob = PyObject_GetAttrString(m_pPyObject, "_obj_");
|
||||
if (real_ob == NULL) {
|
||||
PyErr_Format(PyExc_AttributeError, "The policy object does not have an '_obj_' attribute.");
|
||||
ret = HandleNativeGatewayError(szPropertyName);
|
||||
goto done;
|
||||
}
|
||||
va_list va2;
|
||||
va_start(va2, szPropertyName);
|
||||
PyObject *arg = va_arg( va2, PyObject *);
|
||||
va_end(va2);
|
||||
if (PyObject_SetAttrString(real_ob, (char *)szPropertyName, arg) == 0)
|
||||
ret = NS_OK;
|
||||
else {
|
||||
PyErr_Format(PyExc_AttributeError,
|
||||
"The object does not have a 'set_%s' function, or a '%s attribute.",
|
||||
szPropertyName, szPropertyName);
|
||||
}
|
||||
}
|
||||
if (ret != NS_OK)
|
||||
ret = HandleNativeGatewayError(szPropertyName);
|
||||
done:
|
||||
Py_XDECREF(real_ob);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
|
||||
Some special support to help with object identity.
|
||||
|
||||
In the simplest case, assume a Python COM object is
|
||||
supporting a function "nsIWhatever GetWhatever()",
|
||||
so implements it as:
|
||||
return this
|
||||
it is almost certain they intend returning
|
||||
the same COM OBJECT to the caller! Thus, if a user of this COM
|
||||
object does:
|
||||
|
||||
p1 = foo.GetWhatever();
|
||||
p2 = foo.GetWhatever();
|
||||
|
||||
We almost certainly expect p1==p2==foo.
|
||||
|
||||
We previously _did_ have special support for the "this"
|
||||
example above, but this implements a generic scheme that
|
||||
works for _all_ objects.
|
||||
|
||||
Whenever we are asked to "AutoWrap" a Python object, the
|
||||
first thing we do is see if it has been auto-wrapped before.
|
||||
|
||||
If not, we create a new wrapper, then make a COM weak reference
|
||||
to that wrapper, and store it directly back into the instance
|
||||
we are auto-wrapping! The use of a weak-reference prevents
|
||||
cycles.
|
||||
|
||||
The existance of this attribute in an instance indicates if it
|
||||
has been previously auto-wrapped.
|
||||
|
||||
If it _has_ previously been auto-wrapped, we de-reference the
|
||||
weak reference, and use that gateway.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
nsresult GetDefaultGateway(PyObject *instance, REFNSIID iid, void **ret)
|
||||
{
|
||||
// NOTE: Instance is the real instance, _not_ the policy.
|
||||
PyObject *ob_existing_weak = PyObject_GetAttrString(instance, PyXPCOM_szDefaultGatewayAttributeName);
|
||||
if (ob_existing_weak != NULL) {
|
||||
PRBool ok = PR_TRUE;
|
||||
nsCOMPtr<nsIWeakReference> pWeakRef;
|
||||
ok = NS_SUCCEEDED(Py_nsISupports::InterfaceFromPyObject(ob_existing_weak,
|
||||
NS_GET_IID(nsIWeakReference),
|
||||
getter_AddRefs(pWeakRef),
|
||||
PR_FALSE));
|
||||
Py_DECREF(ob_existing_weak);
|
||||
if (ok)
|
||||
return pWeakRef->QueryReferent( iid, ret);
|
||||
} else
|
||||
PyErr_Clear();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PRBool CheckDefaultGateway(PyObject *real_inst, REFNSIID iid, nsISupports **ret_gateway)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(real_inst, "Did not have an _obj_ attribute");
|
||||
if (real_inst==NULL) {
|
||||
PyErr_Clear();
|
||||
return PR_FALSE;
|
||||
}
|
||||
PyObject *ob_existing_weak = PyObject_GetAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName);
|
||||
if (ob_existing_weak != NULL) {
|
||||
// We have an existing default, but as it is a weak reference, it
|
||||
// may no longer be valid. Check it.
|
||||
PRBool ok = PR_TRUE;
|
||||
nsCOMPtr<nsIWeakReference> pWeakRef;
|
||||
ok = NS_SUCCEEDED(Py_nsISupports::InterfaceFromPyObject(ob_existing_weak,
|
||||
NS_GET_IID(nsIWeakReference),
|
||||
getter_AddRefs(pWeakRef),
|
||||
PR_FALSE));
|
||||
Py_DECREF(ob_existing_weak);
|
||||
if (ok) {
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
ok = NS_SUCCEEDED(pWeakRef->QueryReferent( iid, (void **)(ret_gateway)));
|
||||
Py_END_ALLOW_THREADS;
|
||||
}
|
||||
if (!ok) {
|
||||
// We have the attribute, but not valid - wipe it
|
||||
// before restoring it.
|
||||
if (0 != PyObject_DelAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName))
|
||||
PyErr_Clear();
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
PyErr_Clear();
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void AddDefaultGateway(PyObject *instance, nsISupports *gateway)
|
||||
{
|
||||
// NOTE: Instance is the _policy_!
|
||||
PyObject *real_inst = PyObject_GetAttrString(instance, "_obj_");
|
||||
NS_ABORT_IF_FALSE(real_inst, "Could not get the '_obj_' element");
|
||||
if (!real_inst) return;
|
||||
if (!PyObject_HasAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName)) {
|
||||
nsCOMPtr<nsISupportsWeakReference> swr( do_QueryInterface((nsISupportsWeakReference *)(gateway)) );
|
||||
NS_ABORT_IF_FALSE(swr, "Our gateway failed with a weak reference query");
|
||||
// Create the new default gateway - get a weak reference for our gateway.
|
||||
if (swr) {
|
||||
nsIWeakReference *pWeakReference = NULL;
|
||||
swr->GetWeakReference( &pWeakReference );
|
||||
if (pWeakReference) {
|
||||
PyObject *ob_new_weak = Py_nsISupports::PyObjectFromInterface(pWeakReference,
|
||||
NS_GET_IID(nsIWeakReference),
|
||||
PR_FALSE, /* bAddRef */
|
||||
PR_FALSE ); /* bMakeNicePyObject */
|
||||
// pWeakReference reference consumed.
|
||||
if (ob_new_weak) {
|
||||
PyObject_SetAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName, ob_new_weak);
|
||||
Py_DECREF(ob_new_weak);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Py_DECREF(real_inst);
|
||||
}
|
||||
143
mozilla/extensions/python/xpcom/src/PyGInputStream.cpp
Normal file
143
mozilla/extensions/python/xpcom/src/PyGInputStream.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// PyGInputStream.cpp
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written October 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIInputStream.h>
|
||||
|
||||
class PyG_nsIInputStream : public PyG_Base, public nsIInputStream
|
||||
{
|
||||
public:
|
||||
PyG_nsIInputStream(PyObject *instance) : PyG_Base(instance, NS_GET_IID(nsIInputStream)) {;}
|
||||
PYGATEWAY_BASE_SUPPORT(nsIInputStream, PyG_Base);
|
||||
|
||||
NS_IMETHOD Close(void);
|
||||
NS_IMETHOD Available(PRUint32 *_retval);
|
||||
NS_IMETHOD Read(char * buf, PRUint32 count, PRUint32 *_retval);
|
||||
NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval);
|
||||
NS_IMETHOD GetNonBlocking(PRBool *aNonBlocking);
|
||||
NS_IMETHOD GetObserver(nsIInputStreamObserver * *aObserver);
|
||||
NS_IMETHOD SetObserver(nsIInputStreamObserver * aObserver);
|
||||
};
|
||||
|
||||
|
||||
PyG_Base *MakePyG_nsIInputStream(PyObject *instance)
|
||||
{
|
||||
return new PyG_nsIInputStream(instance);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIInputStream::Close()
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "close";
|
||||
return InvokeNativeViaPolicy(methodName, NULL);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIInputStream::Available(PRUint32 *_retval)
|
||||
{
|
||||
NS_PRECONDITION(_retval, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *ret;
|
||||
const char *methodName = "available";
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
*_retval = PyInt_AsLong(ret);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
Py_XDECREF(ret);
|
||||
}
|
||||
return nr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIInputStream::Read(char * buf, PRUint32 count, PRUint32 *_retval)
|
||||
{
|
||||
NS_PRECONDITION(_retval, "null pointer");
|
||||
NS_PRECONDITION(buf, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *ret;
|
||||
const char *methodName = "read";
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "i", count);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
PRUint32 py_size;
|
||||
const void *py_buf;
|
||||
if (PyObject_AsReadBuffer(ret, &py_buf, (int *)&py_size)!=0) {
|
||||
PyErr_Format(PyExc_TypeError, "nsIInputStream::read() method must return a buffer object - not a '%s' object", ret->ob_type->tp_name);
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
} else {
|
||||
if (py_size > count) {
|
||||
PyXPCOM_LogWarning("nsIInputStream::read() was asked for %d bytes, but the string returned is %d bytes - truncating!\n", count, py_size);
|
||||
py_size = count;
|
||||
}
|
||||
memcpy(buf, py_buf, py_size);
|
||||
*_retval = py_size;
|
||||
}
|
||||
}
|
||||
return nr;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval)
|
||||
{
|
||||
NS_WARNING("ReadSegments() not implemented!!!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIInputStream::GetNonBlocking(PRBool *aNonBlocking)
|
||||
{
|
||||
NS_PRECONDITION(aNonBlocking, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *ret;
|
||||
const char *propName = "nonBlocking";
|
||||
nsresult nr = InvokeNativeGetViaPolicy(propName, &ret);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
*aNonBlocking = PyInt_AsLong(ret);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(propName);
|
||||
Py_XDECREF(ret);
|
||||
}
|
||||
return nr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIInputStream::GetObserver(nsIInputStreamObserver * *aObserver)
|
||||
{
|
||||
NS_PRECONDITION(aObserver, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *ret;
|
||||
const char *propName = "observer";
|
||||
nsresult nr = InvokeNativeGetViaPolicy(propName, &ret);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
Py_nsISupports::InterfaceFromPyObject(ret, NS_GET_IID(nsIInputStreamObserver), (nsISupports **)aObserver, PR_FALSE);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(propName);
|
||||
}
|
||||
return nr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIInputStream::SetObserver(nsIInputStreamObserver * aObserver)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *propName = "observer";
|
||||
PyObject *obObserver = MakeInterfaceParam(aObserver, &NS_GET_IID(nsIInputStreamObserver));
|
||||
if (obObserver==NULL)
|
||||
return HandleNativeGatewayError(propName);
|
||||
nsresult nr = InvokeNativeSetViaPolicy(propName, obObserver);
|
||||
Py_DECREF(obObserver);
|
||||
return nr;
|
||||
}
|
||||
331
mozilla/extensions/python/xpcom/src/PyGModule.cpp
Normal file
331
mozilla/extensions/python/xpcom/src/PyGModule.cpp
Normal file
@@ -0,0 +1,331 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
// Unfortunately, we can not use an XPConnect object for
|
||||
// the nsiModule and nsiComponentLoader interfaces.
|
||||
// As XPCOM shuts down, it shuts down the interface manager before
|
||||
// it releases all the modules. This is a bit of a problem for
|
||||
// us, as it means we can't get runtime info on the interface at shutdown time.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIModule.h>
|
||||
#include <nsIComponentLoader.h>
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Can only assume dynamic loading on Windows.
|
||||
#define LOADER_LINKS_WITH_PYTHON
|
||||
|
||||
#endif // XP_WIN
|
||||
|
||||
extern void PyXPCOM_InterpreterState_Ensure();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// This is the main entry point called by the Python component
|
||||
// loader.
|
||||
extern "C" NS_EXPORT nsresult PyXPCOM_NSGetModule(nsIComponentManager *servMgr,
|
||||
nsIFile* location,
|
||||
nsIModule** result)
|
||||
{
|
||||
NS_PRECONDITION(result!=NULL, "null result pointer in PyXPCOM_NSGetModule!");
|
||||
NS_PRECONDITION(location!=NULL, "null nsIFile pointer in PyXPCOM_NSGetModule!");
|
||||
NS_PRECONDITION(servMgr!=NULL, "null servMgr pointer in PyXPCOM_NSGetModule!");
|
||||
#ifndef LOADER_LINKS_WITH_PYTHON
|
||||
if (!Py_IsInitialized()) {
|
||||
Py_Initialize();
|
||||
if (!Py_IsInitialized()) {
|
||||
PyXPCOM_LogError("Python initialization failed!\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PyEval_InitThreads();
|
||||
PyXPCOM_InterpreterState_Ensure();
|
||||
PyEval_SaveThread();
|
||||
}
|
||||
#endif // LOADER_LINKS_WITH_PYTHON
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *func = NULL;
|
||||
PyObject *obServMgr = NULL;
|
||||
PyObject *obLocation = NULL;
|
||||
PyObject *wrap_ret = NULL;
|
||||
PyObject *args = NULL;
|
||||
PyObject *mod = PyImport_ImportModule("xpcom.server");
|
||||
if (!mod) goto done;
|
||||
func = PyObject_GetAttrString(mod, "NS_GetModule");
|
||||
if (func==NULL) goto done;
|
||||
obServMgr = Py_nsISupports::PyObjectFromInterface(servMgr, NS_GET_IID(nsIComponentManager), PR_TRUE);
|
||||
if (obServMgr==NULL) goto done;
|
||||
obLocation = Py_nsISupports::PyObjectFromInterface(location, NS_GET_IID(nsIFile), PR_TRUE);
|
||||
if (obLocation==NULL) goto done;
|
||||
args = Py_BuildValue("OO", obServMgr, obLocation);
|
||||
if (args==NULL) goto done;
|
||||
wrap_ret = PyEval_CallObject(func, args);
|
||||
if (wrap_ret==NULL) goto done;
|
||||
Py_nsISupports::InterfaceFromPyObject(wrap_ret, NS_GET_IID(nsIModule), (nsISupports **)result, PR_FALSE, PR_FALSE);
|
||||
done:
|
||||
nsresult nr = NS_OK;
|
||||
if (PyErr_Occurred()) {
|
||||
PyXPCOM_LogError("Obtaining the module object from Python failed.\n");
|
||||
nr = PyXPCOM_SetCOMErrorFromPyException();
|
||||
}
|
||||
Py_XDECREF(func);
|
||||
Py_XDECREF(obServMgr);
|
||||
Py_XDECREF(obLocation);
|
||||
Py_XDECREF(wrap_ret);
|
||||
Py_XDECREF(mod);
|
||||
Py_XDECREF(args);
|
||||
return nr;
|
||||
}
|
||||
|
||||
class PyG_nsIModule : public PyG_Base, public nsIModule
|
||||
{
|
||||
public:
|
||||
PyG_nsIModule(PyObject *instance) : PyG_Base(instance, NS_GET_IID(nsIModule)) {;}
|
||||
PYGATEWAY_BASE_SUPPORT(nsIModule, PyG_Base);
|
||||
|
||||
NS_IMETHOD GetClassObject(nsIComponentManager *aCompMgr, const nsCID & aClass, const nsIID & aIID, void * *result);
|
||||
NS_IMETHOD RegisterSelf(nsIComponentManager *aCompMgr, nsIFile *location, const char *registryLocation, const char *componentType);
|
||||
NS_IMETHOD UnregisterSelf(nsIComponentManager *aCompMgr, nsIFile *location, const char *registryLocation);
|
||||
NS_IMETHOD CanUnload(nsIComponentManager *aCompMgr, PRBool *_retval);
|
||||
};
|
||||
|
||||
PyG_Base *MakePyG_nsIModule(PyObject *instance)
|
||||
{
|
||||
return new PyG_nsIModule(instance);
|
||||
}
|
||||
|
||||
|
||||
// Create a factory object for creating instances of aClass.
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIModule::GetClassObject(nsIComponentManager *aCompMgr,
|
||||
const nsCID& aClass,
|
||||
const nsIID& aIID,
|
||||
void** r_classObj)
|
||||
{
|
||||
NS_PRECONDITION(r_classObj, "null pointer");
|
||||
*r_classObj = nsnull;
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *cm = MakeInterfaceParam(aCompMgr, &NS_GET_IID(nsIComponentManager));
|
||||
PyObject *iid = Py_nsIID::PyObjectFromIID(aIID);
|
||||
PyObject *clsid = Py_nsIID::PyObjectFromIID(aClass);
|
||||
const char *methodName = "getClassObject";
|
||||
PyObject *ret = NULL;
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "OOO", cm, clsid, iid);
|
||||
Py_XDECREF(cm);
|
||||
Py_XDECREF(iid);
|
||||
Py_XDECREF(clsid);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
nr = Py_nsISupports::InterfaceFromPyObject(ret, aIID, (nsISupports **)r_classObj, PR_FALSE);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
}
|
||||
if (NS_FAILED(nr)) {
|
||||
NS_ABORT_IF_FALSE(*r_classObj==NULL, "returning error result with an interface - probable leak!");
|
||||
}
|
||||
Py_XDECREF(ret);
|
||||
return nr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIModule::RegisterSelf(nsIComponentManager *aCompMgr,
|
||||
nsIFile* aPath,
|
||||
const char* registryLocation,
|
||||
const char* componentType)
|
||||
{
|
||||
NS_PRECONDITION(aCompMgr, "null pointer");
|
||||
NS_PRECONDITION(aPath, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *cm = MakeInterfaceParam(aCompMgr, &NS_GET_IID(nsIComponentManager));
|
||||
PyObject *path = MakeInterfaceParam(aPath, &NS_GET_IID(nsIFile));
|
||||
const char *methodName = "registerSelf";
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OOzz", cm, path, registryLocation, componentType);
|
||||
Py_XDECREF(cm);
|
||||
Py_XDECREF(path);
|
||||
return nr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIModule::UnregisterSelf(nsIComponentManager* aCompMgr,
|
||||
nsIFile* aPath,
|
||||
const char* registryLocation)
|
||||
{
|
||||
NS_PRECONDITION(aCompMgr, "null pointer");
|
||||
NS_PRECONDITION(aPath, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *cm = MakeInterfaceParam(aCompMgr, &NS_GET_IID(nsIComponentManager));
|
||||
PyObject *path = MakeInterfaceParam(aPath, &NS_GET_IID(nsIFile));
|
||||
const char *methodName = "unregisterSelf";
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OOz", cm, path, registryLocation);
|
||||
Py_XDECREF(cm);
|
||||
Py_XDECREF(path);
|
||||
return nr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload)
|
||||
{
|
||||
NS_PRECONDITION(aCompMgr, "null pointer");
|
||||
NS_PRECONDITION(okToUnload, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *cm = MakeInterfaceParam(aCompMgr, &NS_GET_IID(nsIComponentManager));
|
||||
const char *methodName = "canUnload";
|
||||
PyObject *ret = NULL;
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "O", cm);
|
||||
Py_XDECREF(cm);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
*okToUnload = PyInt_AsLong(ret);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
}
|
||||
Py_XDECREF(ret);
|
||||
return nr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class PyG_nsIComponentLoader : public PyG_Base, public nsIComponentLoader
|
||||
{
|
||||
public:
|
||||
PyG_nsIComponentLoader(PyObject *instance) : PyG_Base(instance, NS_GET_IID(nsIComponentLoader)) {;}
|
||||
PYGATEWAY_BASE_SUPPORT(nsIComponentLoader, PyG_Base);
|
||||
|
||||
NS_DECL_NSICOMPONENTLOADER
|
||||
};
|
||||
|
||||
PyG_Base *MakePyG_nsIComponentLoader(PyObject *instance)
|
||||
{
|
||||
return new PyG_nsIComponentLoader(instance);
|
||||
}
|
||||
|
||||
/* nsIFactory getFactory (in nsIIDRef aCID, in string aLocation, in string aType); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::GetFactory(const nsIID & aCID, const char *aLocation, const char *aType, nsIFactory **_retval)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "getFactory";
|
||||
PyObject *iid = Py_nsIID::PyObjectFromIID(aCID);
|
||||
PyObject *ret = NULL;
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "Ozz",
|
||||
iid,
|
||||
aLocation,
|
||||
aType);
|
||||
Py_XDECREF(iid);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
Py_nsISupports::InterfaceFromPyObject(ret, NS_GET_IID(nsIFactory), (nsISupports **)_retval, PR_FALSE);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
}
|
||||
Py_XDECREF(ret);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/* void init (in nsIComponentManager aCompMgr, in nsISupports aRegistry); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aRegistry)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "init";
|
||||
PyObject *c = MakeInterfaceParam(aCompMgr, &NS_GET_IID(nsIComponentManager));
|
||||
PyObject *r = MakeInterfaceParam(aRegistry, &NS_GET_IID(nsISupports));
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OO", c, r);
|
||||
Py_XDECREF(c);
|
||||
Py_XDECREF(r);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/* void onRegister (in nsIIDRef aCID, in string aType, in string aClassName, in string aContractID, in string aLocation, in boolean aReplace, in boolean aPersist); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::OnRegister(const nsIID & aCID, const char *aType, const char *aClassName, const char *aContractID, const char *aLocation, PRBool aReplace, PRBool aPersist)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "onRegister";
|
||||
PyObject *iid = Py_nsIID::PyObjectFromIID(aCID);
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "Ossssii",
|
||||
iid,
|
||||
aType,
|
||||
aClassName,
|
||||
aContractID,
|
||||
aLocation,
|
||||
aReplace,
|
||||
aPersist);
|
||||
Py_XDECREF(iid);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/* void autoRegisterComponents (in long aWhen, in nsIFile aDirectory); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::AutoRegisterComponents(PRInt32 aWhen, nsIFile *aDirectory)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "autoRegisterComponents";
|
||||
PyObject *c = MakeInterfaceParam(aDirectory, &NS_GET_IID(nsIFile));
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "iO", aWhen, c);
|
||||
Py_XDECREF(c);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/* boolean autoRegisterComponent (in long aWhen, in nsIFile aComponent); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::AutoRegisterComponent(PRInt32 aWhen, nsIFile *aComponent, PRBool *_retval)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "autoRegisterComponent";
|
||||
PyObject *ret = NULL;
|
||||
PyObject *c = MakeInterfaceParam(aComponent, &NS_GET_IID(nsIFile));
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "iO", aWhen, c);
|
||||
Py_XDECREF(c);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
*_retval = PyInt_AsLong(ret);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
}
|
||||
Py_XDECREF(ret);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/* boolean autoUnregisterComponent (in long aWhen, in nsIFile aComponent); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::AutoUnregisterComponent(PRInt32 aWhen, nsIFile *aComponent, PRBool *_retval)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "autoUnregisterComponent";
|
||||
PyObject *ret = NULL;
|
||||
PyObject *c = MakeInterfaceParam(aComponent, &NS_GET_IID(nsIFile));
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "iO", aWhen, c);
|
||||
Py_XDECREF(c);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
*_retval = PyInt_AsLong(ret);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
}
|
||||
Py_XDECREF(ret);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/* boolean registerDeferredComponents (in long aWhen); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::RegisterDeferredComponents(PRInt32 aWhen, PRBool *_retval)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "registerDeferredComponents";
|
||||
PyObject *ret = NULL;
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "i", aWhen);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
*_retval = PyInt_AsLong(ret);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
}
|
||||
Py_XDECREF(ret);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/* void unloadAll (in long aWhen); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::UnloadAll(PRInt32 aWhen)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "unloadAll";
|
||||
return InvokeNativeViaPolicy(methodName, NULL, "i", aWhen);
|
||||
}
|
||||
|
||||
|
||||
144
mozilla/extensions/python/xpcom/src/PyGStub.cpp
Normal file
144
mozilla/extensions/python/xpcom/src/PyGStub.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// PyXPTStub - the stub for implementing interfaces.
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIInterfaceInfoManager.h>
|
||||
|
||||
void *PyXPCOM_XPTStub::ThisAsIID(const nsIID &iid)
|
||||
{
|
||||
if (iid.Equals(NS_GET_IID(nsISupports)))
|
||||
return (nsISupports *)(nsXPTCStubBase *)this;
|
||||
else if (iid.Equals(m_iid))
|
||||
return (nsISupports *)(nsXPTCStubBase *)this;
|
||||
else
|
||||
return PyG_Base::ThisAsIID(iid);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyXPCOM_XPTStub::GetInterfaceInfo(nsIInterfaceInfo** info)
|
||||
{
|
||||
NS_PRECONDITION(info, "NULL pointer");
|
||||
if (info==nsnull)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
// Simply get the XPCOM runtime to provide this
|
||||
// (but there must be some reason why they dont get it themselves!?
|
||||
// Maybe because they dont know the IID?
|
||||
nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
|
||||
NS_ABORT_IF_FALSE(iim != nsnull, "Cant get interface from IIM!");
|
||||
if (iim==nsnull)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return iim->GetInfoForIID( &m_iid, info);
|
||||
}
|
||||
|
||||
// call this method and return result
|
||||
NS_IMETHODIMP
|
||||
PyXPCOM_XPTStub::CallMethod(PRUint16 methodIndex,
|
||||
const nsXPTMethodInfo* info,
|
||||
nsXPTCMiniVariant* params)
|
||||
{
|
||||
nsresult rc = NS_ERROR_FAILURE;
|
||||
NS_PRECONDITION(info, "NULL methodinfo pointer");
|
||||
NS_PRECONDITION(params, "NULL variant pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *obParams = NULL;
|
||||
PyObject *result = NULL;
|
||||
PyObject *obThisObject = NULL;
|
||||
PyObject *obMI = PyObject_FromXPTMethodDescriptor(info);
|
||||
PyXPCOM_GatewayVariantHelper arg_helper(this, methodIndex, info, params);
|
||||
if (obMI==NULL)
|
||||
goto done;
|
||||
// base object is passed raw.
|
||||
obThisObject = Py_nsISupports::PyObjectFromInterface((nsIInternalPython*)this, NS_GET_IID(nsISupports), PR_TRUE, PR_FALSE);
|
||||
obParams = arg_helper.MakePyArgs();
|
||||
if (obParams==NULL)
|
||||
goto done;
|
||||
result = PyObject_CallMethod(m_pPyObject,
|
||||
"_CallMethod_",
|
||||
"OiOO",
|
||||
obThisObject,
|
||||
(int)methodIndex,
|
||||
obMI,
|
||||
obParams);
|
||||
if (result!=NULL) {
|
||||
rc = arg_helper.ProcessPythonResult(result);
|
||||
// Use an xor to check failure && pyerr, or !failure && !pyerr.
|
||||
NS_ABORT_IF_FALSE( ((NS_FAILED(rc)!=0)^(PyErr_Occurred()!=0)) == 0, "We must have failure with a Python error, or success without a Python error.");
|
||||
}
|
||||
done:
|
||||
if (PyErr_Occurred()) {
|
||||
// The error handling - fairly involved, but worth it as
|
||||
// good error reporting is critical for users to know WTF
|
||||
// is going on - especially with TypeErrors etc in their
|
||||
// return values (ie, after the Python code has successfully
|
||||
// existed, but we encountered errors unpacking their
|
||||
// result values for the COM caller - there is literally no
|
||||
// way to catch these exceptions from Python code, as their
|
||||
// is no Python function on the call-stack)
|
||||
|
||||
// First line of attack in an error is to call-back on the policy.
|
||||
// If the callback of the error handler succeeds and returns an
|
||||
// integer (for the nsresult), we take no further action.
|
||||
|
||||
// If this callback fails, we log _2_ exceptions - the error handler
|
||||
// error, and the original error.
|
||||
|
||||
PRBool bProcessMainError = PR_TRUE; // set to false if our exception handler does its thing!
|
||||
PyObject *exc_typ, *exc_val, *exc_tb;
|
||||
PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
|
||||
PyErr_NormalizeException( &exc_typ, &exc_val, &exc_tb);
|
||||
|
||||
PyObject *err_result = PyObject_CallMethod(m_pPyObject,
|
||||
"_CallMethodException_",
|
||||
"OiOO(OOO)",
|
||||
obThisObject,
|
||||
(int)methodIndex,
|
||||
obMI,
|
||||
obParams,
|
||||
exc_typ ? exc_typ : Py_None, // should never be NULL, but defensive programming...
|
||||
exc_val ? exc_val : Py_None, // may well be NULL.
|
||||
exc_tb ? exc_tb : Py_None); // may well be NULL.
|
||||
if (err_result == NULL) {
|
||||
PyXPCOM_LogError("The exception handler _CallMethodException_ failed!\n");
|
||||
} else if (err_result == Py_None) {
|
||||
// The exception handler has chosen not to do anything with
|
||||
// this error, so we still need to print it!
|
||||
;
|
||||
} else if (PyInt_Check(err_result)) {
|
||||
// The exception handler has given us the nresult.
|
||||
rc = PyInt_AsLong(err_result);
|
||||
bProcessMainError = PR_FALSE;
|
||||
} else {
|
||||
// The exception handler succeeded, but returned other than
|
||||
// int or None.
|
||||
PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", err_result->ob_type->tp_name);
|
||||
}
|
||||
Py_XDECREF(err_result);
|
||||
PyErr_Restore(exc_typ, exc_val, exc_tb);
|
||||
if (bProcessMainError) {
|
||||
PyXPCOM_LogError("The function '%s' failed\n", info->GetName());
|
||||
rc = PyXPCOM_SetCOMErrorFromPyException();
|
||||
}
|
||||
// else everything is already setup,
|
||||
// just clear the Python error state.
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
Py_XDECREF(obMI);
|
||||
Py_XDECREF(obParams);
|
||||
Py_XDECREF(obThisObject);
|
||||
Py_XDECREF(result);
|
||||
return rc;
|
||||
}
|
||||
51
mozilla/extensions/python/xpcom/src/PyGWeakReference.cpp
Normal file
51
mozilla/extensions/python/xpcom/src/PyGWeakReference.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// PyGWeakReference - implements weak references for gateways.
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written November 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
|
||||
PyXPCOM_GatewayWeakReference::PyXPCOM_GatewayWeakReference( PyG_Base *base )
|
||||
{
|
||||
m_pBase = base;
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
PyXPCOM_GatewayWeakReference::~PyXPCOM_GatewayWeakReference()
|
||||
{
|
||||
// Simply zap my reference to the gateway!
|
||||
// No need to zap my gateway's reference to me, as
|
||||
// it already holds a reference, so if we are destructing,
|
||||
// then it can't possibly hold one.
|
||||
m_pBase = NULL;
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(PyXPCOM_GatewayWeakReference);
|
||||
NS_IMPL_THREADSAFE_RELEASE(PyXPCOM_GatewayWeakReference);
|
||||
NS_IMPL_THREADSAFE_QUERY_INTERFACE(PyXPCOM_GatewayWeakReference, NS_GET_IID(nsIWeakReference));
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyXPCOM_GatewayWeakReference::QueryReferent(REFNSIID iid, void * *ret)
|
||||
{
|
||||
{
|
||||
// Temp scope for lock. We can't hold the lock during
|
||||
// a QI, as this may itself need the lock.
|
||||
// Make sure our object isn't dieing right now on another thread.
|
||||
CEnterLeaveXPCOMFramework _celf;
|
||||
if (m_pBase == NULL)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
m_pBase->AddRef(); // Can't die while we have a ref.
|
||||
} // end of lock scope - lock unlocked.
|
||||
nsresult nr = m_pBase->QueryInterface(iid, ret);
|
||||
m_pBase->Release();
|
||||
return nr;
|
||||
}
|
||||
165
mozilla/extensions/python/xpcom/src/PyIComponentManager.cpp
Normal file
165
mozilla/extensions/python/xpcom/src/PyIComponentManager.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIComponentManager.h>
|
||||
|
||||
static nsIComponentManager *GetI(PyObject *self) {
|
||||
nsIID iid = NS_GET_IID(nsIComponentManager);
|
||||
|
||||
if (!Py_nsISupports::Check(self, iid)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
|
||||
return NULL;
|
||||
}
|
||||
return (nsIComponentManager *)Py_nsISupports::GetI(self);
|
||||
}
|
||||
|
||||
static PyObject *PyCreateInstanceByContractID(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *pid, *notyet = NULL;
|
||||
PyObject *obIID = NULL;
|
||||
if (!PyArg_ParseTuple(args, "s|zO", &pid, ¬yet, &obIID))
|
||||
return NULL;
|
||||
if (notyet != NULL) {
|
||||
PyErr_SetString(PyExc_ValueError, "2nd arg must be none");
|
||||
return NULL;
|
||||
}
|
||||
nsIComponentManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
if (obIID==NULL)
|
||||
iid = NS_GET_IID(nsISupports);
|
||||
else
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
|
||||
nsISupports *pis;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->CreateInstanceByContractID(pid, NULL, iid, (void **)&pis);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyContractIDToClassID(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *pid;
|
||||
if (!PyArg_ParseTuple(args, "s", &pid))
|
||||
return NULL;
|
||||
nsIComponentManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->ContractIDToClassID(pid, &iid);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
return Py_nsIID::PyObjectFromIID(iid);
|
||||
}
|
||||
|
||||
static PyObject *PyCLSIDToContractID(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID;
|
||||
if (!PyArg_ParseTuple(args, "O", &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
char *ret_pid = nsnull;
|
||||
char *ret_class = nsnull;
|
||||
nsIComponentManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->CLSIDToContractID(iid, &ret_class, &ret_pid);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
PyObject *ob_pid = PyString_FromString(ret_pid);
|
||||
PyObject *ob_class = PyString_FromString(ret_class);
|
||||
PyObject *ret = Py_BuildValue("OO", ob_pid, ob_class);
|
||||
nsAllocator::Free(ret_pid);
|
||||
nsAllocator::Free(ret_class);
|
||||
Py_XDECREF(ob_pid);
|
||||
Py_XDECREF(ob_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *PyEnumerateCLSIDs(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
|
||||
nsIComponentManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIEnumerator *pRet;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->EnumerateCLSIDs(&pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator), PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyEnumerateContractIDs(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
|
||||
nsIComponentManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIEnumerator *pRet;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->EnumerateContractIDs(&pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator), PR_FALSE);
|
||||
}
|
||||
|
||||
struct PyMethodDef
|
||||
PyMethods_IComponentManager[] =
|
||||
{
|
||||
{ "CreateInstanceByContractID", PyCreateInstanceByContractID, 1},
|
||||
{ "createInstanceByContractID", PyCreateInstanceByContractID, 1},
|
||||
{ "EnumerateCLSIDs", PyEnumerateCLSIDs, 1},
|
||||
{ "enumerateCLSIDs", PyEnumerateCLSIDs, 1},
|
||||
{ "EnumerateContractIDs", PyEnumerateContractIDs, 1},
|
||||
{ "enumerateContractIDs", PyEnumerateContractIDs, 1},
|
||||
{ "ContractIDToClassID", PyContractIDToClassID, 1},
|
||||
{ "contractIDToClassID", PyContractIDToClassID, 1},
|
||||
{ "CLSIDToContractID", PyCLSIDToContractID, 1},
|
||||
{NULL}
|
||||
};
|
||||
198
mozilla/extensions/python/xpcom/src/PyIEnumerator.cpp
Normal file
198
mozilla/extensions/python/xpcom/src/PyIEnumerator.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIEnumerator.h>
|
||||
|
||||
static nsIEnumerator *GetI(PyObject *self) {
|
||||
nsIID iid = NS_GET_IID(nsIEnumerator);
|
||||
|
||||
if (!Py_nsISupports::Check(self, iid)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
|
||||
return NULL;
|
||||
}
|
||||
return (nsIEnumerator *)Py_nsISupports::GetI(self);
|
||||
}
|
||||
|
||||
static PyObject *PyFirst(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":First"))
|
||||
return NULL;
|
||||
|
||||
nsIEnumerator *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->First();
|
||||
Py_END_ALLOW_THREADS;
|
||||
return PyInt_FromLong(r);
|
||||
}
|
||||
|
||||
static PyObject *PyNext(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":Next"))
|
||||
return NULL;
|
||||
|
||||
nsIEnumerator *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->Next();
|
||||
Py_END_ALLOW_THREADS;
|
||||
return PyInt_FromLong(r);
|
||||
}
|
||||
|
||||
static PyObject *PyCurrentItem(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID = NULL;
|
||||
if (!PyArg_ParseTuple(args, "|O:CurrentItem", &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIID iid(NS_GET_IID(nsISupports));
|
||||
if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
nsIEnumerator *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsISupports *pRet = nsnull;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->CurrentItem(&pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
if (obIID) {
|
||||
nsISupports *temp;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pRet->QueryInterface(iid, (void **)&temp);
|
||||
pRet->Release();
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) ) {
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
}
|
||||
pRet = temp;
|
||||
}
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, iid, PR_FALSE);
|
||||
}
|
||||
|
||||
// A method added for Python performance if you really need
|
||||
// it. Allows you to fetch a block of objects in one
|
||||
// hit, allowing the loop to remain implemented in C.
|
||||
static PyObject *PyFetchBlock(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID = NULL;
|
||||
int n_wanted;
|
||||
int n_fetched = 0;
|
||||
if (!PyArg_ParseTuple(args, "i|O:FetchBlock", &n_wanted, &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIID iid(NS_GET_IID(nsISupports));
|
||||
if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
nsIEnumerator *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
// We want to fetch with the thread-lock released,
|
||||
// but this means we can not append to the PyList
|
||||
nsISupports **fetched = new nsISupports*[n_wanted];
|
||||
if (fetched==nsnull) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
memset(fetched, 0, sizeof(nsISupports *) * n_wanted);
|
||||
nsresult r = NS_OK;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
for (;n_fetched<n_wanted;) {
|
||||
nsISupports *pNew;
|
||||
r = pI->CurrentItem(&pNew);
|
||||
if (NS_FAILED(r)) {
|
||||
r = 0; // Normal enum end
|
||||
break;
|
||||
}
|
||||
if (obIID) {
|
||||
nsISupports *temp;
|
||||
r = pNew->QueryInterface(iid, (void **)&temp);
|
||||
pNew->Release();
|
||||
if ( NS_FAILED(r) ) {
|
||||
break;
|
||||
}
|
||||
pNew = temp;
|
||||
}
|
||||
fetched[n_fetched] = pNew;
|
||||
n_fetched++; // must increment before breaking out.
|
||||
if (NS_FAILED(pI->Next()))
|
||||
break; // not an error condition.
|
||||
}
|
||||
Py_END_ALLOW_THREADS;
|
||||
PyObject *ret;
|
||||
if (NS_SUCCEEDED(r)) {
|
||||
ret = PyList_New(n_fetched);
|
||||
if (ret)
|
||||
for (int i=0;i<n_fetched;i++) {
|
||||
PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid, PR_FALSE);
|
||||
PyList_SET_ITEM(ret, i, new_ob);
|
||||
}
|
||||
} else
|
||||
ret = PyXPCOM_BuildPyException(r);
|
||||
|
||||
if ( ret == NULL ) {
|
||||
// Free the objects we consumed.
|
||||
for (int i=0;i<n_fetched;i++)
|
||||
fetched[i]->Release();
|
||||
|
||||
}
|
||||
delete [] fetched;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *PyIsDone(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":IsDone"))
|
||||
return NULL;
|
||||
|
||||
nsIEnumerator *pI = GetI(self);
|
||||
nsresult r;
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->IsDone();
|
||||
Py_END_ALLOW_THREADS;
|
||||
if (NS_FAILED(r))
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
PyObject *ret = r==NS_OK ? Py_True : Py_False;
|
||||
Py_INCREF(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct PyMethodDef
|
||||
PyMethods_IEnumerator[] =
|
||||
{
|
||||
{ "First", PyFirst, 1},
|
||||
{ "first", PyFirst, 1},
|
||||
{ "Next", PyNext, 1},
|
||||
{ "next", PyNext, 1},
|
||||
{ "CurrentItem", PyCurrentItem, 1},
|
||||
{ "currentItem", PyCurrentItem, 1},
|
||||
{ "IsDone", PyIsDone, 1},
|
||||
{ "isDone", PyIsDone, 1},
|
||||
{ "FetchBlock", PyFetchBlock, 1},
|
||||
{ "fetchBlock", PyFetchBlock, 1},
|
||||
{NULL}
|
||||
};
|
||||
202
mozilla/extensions/python/xpcom/src/PyIID.cpp
Normal file
202
mozilla/extensions/python/xpcom/src/PyIID.cpp
Normal file
@@ -0,0 +1,202 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// Py_nsIID.cpp -- IID type for Python/XPCOM
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
//
|
||||
// @doc
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIInterfaceInfoManager.h>
|
||||
|
||||
nsIID Py_nsIID_NULL = {0,0,0,{0,0,0,0,0,0,0,0}};
|
||||
|
||||
// @pymethod <o Py_nsIID>|xpcom|IID|Creates a new IID object
|
||||
PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID;
|
||||
PyObject *obBuf;
|
||||
if ( PyArg_ParseTuple(args, "O", &obBuf)) {
|
||||
if (PyBuffer_Check(obBuf)) {
|
||||
PyBufferProcs *pb = NULL;
|
||||
pb = obBuf->ob_type->tp_as_buffer;
|
||||
void *buf = NULL;
|
||||
int size = (*pb->bf_getreadbuffer)(obBuf, 0, &buf);
|
||||
if (size != sizeof(nsIID) || buf==NULL) {
|
||||
PyErr_Format(PyExc_ValueError, "A buffer object to be converted to an IID must be exactly %d bytes long", sizeof(nsIID));
|
||||
return NULL;
|
||||
}
|
||||
nsIID iid;
|
||||
unsigned char *ptr = (unsigned char *)buf;
|
||||
iid.m0 = XPT_SWAB32(*((PRUint32 *)ptr));
|
||||
ptr = ((unsigned char *)buf) + offsetof(nsIID, m1);
|
||||
iid.m1 = XPT_SWAB16(*((PRUint16 *)ptr));
|
||||
ptr = ((unsigned char *)buf) + offsetof(nsIID, m2);
|
||||
iid.m2 = XPT_SWAB16(*((PRUint16 *)ptr));
|
||||
ptr = ((unsigned char *)buf) + offsetof(nsIID, m3);
|
||||
for (int i=0;i<8;i++) {
|
||||
iid.m3[i] = *((PRUint8 *)ptr);
|
||||
ptr += sizeof(PRUint8);
|
||||
}
|
||||
return new Py_nsIID(iid);
|
||||
}
|
||||
}
|
||||
PyErr_Clear();
|
||||
// @pyparm string/Unicode|iidString||A string representation of an IID, or a ContractID.
|
||||
if ( !PyArg_ParseTuple(args, "O", &obIID) )
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
return new Py_nsIID(iid);
|
||||
}
|
||||
|
||||
/*static*/ PRBool
|
||||
Py_nsIID::IIDFromPyObject(PyObject *ob, nsIID *pRet) {
|
||||
PRBool ok = PR_TRUE;
|
||||
nsIID iid;
|
||||
if (ob==NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "The object is invalid!");
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (PyString_Check(ob)) {
|
||||
ok = iid.Parse(PyString_AsString(ob));
|
||||
if (!ok) {
|
||||
PyXPCOM_BuildPyException(NS_ERROR_ILLEGAL_VALUE);
|
||||
return PR_FALSE;
|
||||
}
|
||||
} else if (ob->ob_type == &type) {
|
||||
iid = ((Py_nsIID *)ob)->m_iid;
|
||||
} else if (PyInstance_Check(ob)) {
|
||||
// Get the _iidobj_ attribute
|
||||
PyObject *use_ob = PyObject_GetAttrString(ob, "_iidobj_");
|
||||
if (use_ob==NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "Only instances with _iidobj_ attributes can be used as IID objects");
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (use_ob->ob_type != &type) {
|
||||
Py_DECREF(use_ob);
|
||||
PyErr_SetString(PyExc_TypeError, "instance _iidobj_ attributes must be raw IID object");
|
||||
return PR_FALSE;
|
||||
}
|
||||
iid = ((Py_nsIID *)use_ob)->m_iid;
|
||||
Py_DECREF(use_ob);
|
||||
} else {
|
||||
PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an IID", ob->ob_type->tp_name);
|
||||
ok = PR_FALSE;
|
||||
}
|
||||
if (ok) *pRet = iid;
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
// @object Py_nsIID|A Python object, representing an IID/CLSID.
|
||||
// <nl>All pythoncom functions that return a CLSID/IID will return one of these
|
||||
// objects. However, in almost all cases, functions that expect a CLSID/IID
|
||||
// as a param will accept either a string object, or a native Py_nsIID object.
|
||||
PyTypeObject Py_nsIID::type =
|
||||
{
|
||||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0,
|
||||
"IID",
|
||||
sizeof(Py_nsIID),
|
||||
0,
|
||||
PyTypeMethod_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
PyTypeMethod_getattr, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
PyTypeMethod_compare, /* tp_compare */
|
||||
PyTypeMethod_repr, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
PyTypeMethod_hash, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
PyTypeMethod_str, /* tp_str */
|
||||
};
|
||||
|
||||
Py_nsIID::Py_nsIID(const nsIID &riid)
|
||||
{
|
||||
ob_type = &type;
|
||||
_Py_NewReference(this);
|
||||
m_iid = riid;
|
||||
}
|
||||
|
||||
/*static*/PyObject *
|
||||
Py_nsIID::PyTypeMethod_getattr(PyObject *self, char *name)
|
||||
{
|
||||
Py_nsIID *me = (Py_nsIID *)self;
|
||||
if (strcmp(name, "name")==0) {
|
||||
char *iid_repr = nsnull;
|
||||
nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
|
||||
if (iim!=nsnull)
|
||||
iim->GetNameForIID(&me->m_iid, &iid_repr);
|
||||
if (iid_repr==nsnull)
|
||||
iid_repr = me->m_iid.ToString();
|
||||
PyObject *ret;
|
||||
if (iid_repr != nsnull) {
|
||||
ret = PyString_FromString(iid_repr);
|
||||
nsAllocator::Free(iid_repr);
|
||||
} else
|
||||
ret = PyString_FromString("<cant get IID info!>");
|
||||
return ret;
|
||||
}
|
||||
return PyErr_Format(PyExc_AttributeError, "IID objects have no attribute '%s'", name);
|
||||
}
|
||||
|
||||
/* static */ int
|
||||
Py_nsIID::PyTypeMethod_compare(PyObject *self, PyObject *other)
|
||||
{
|
||||
Py_nsIID *s_iid = (Py_nsIID *)self;
|
||||
Py_nsIID *o_iid = (Py_nsIID *)other;
|
||||
return memcmp(&s_iid->m_iid, &o_iid->m_iid, sizeof(s_iid->m_iid));
|
||||
}
|
||||
|
||||
/* static */ PyObject *
|
||||
Py_nsIID::PyTypeMethod_repr(PyObject *self)
|
||||
{
|
||||
Py_nsIID *s_iid = (Py_nsIID *)self;
|
||||
char buf[256];
|
||||
char *sziid = s_iid->m_iid.ToString();
|
||||
sprintf(buf, "_xpcom.IID('%s')", sziid);
|
||||
nsAllocator::Free(sziid);
|
||||
return PyString_FromString(buf);
|
||||
}
|
||||
|
||||
/* static */ PyObject *
|
||||
Py_nsIID::PyTypeMethod_str(PyObject *self)
|
||||
{
|
||||
Py_nsIID *s_iid = (Py_nsIID *)self;
|
||||
char *sziid = s_iid->m_iid.ToString();
|
||||
PyObject *ret = PyString_FromString(sziid);
|
||||
nsAllocator::Free(sziid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* static */long
|
||||
Py_nsIID::PyTypeMethod_hash(PyObject *self)
|
||||
{
|
||||
const nsIID &iid = ((Py_nsIID *)self)->m_iid;
|
||||
|
||||
long ret = iid.m0 + iid.m1 + iid.m2;
|
||||
for (int i=0;i<7;i++)
|
||||
ret += iid.m3[i];
|
||||
if ( ret == -1 )
|
||||
return -2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
Py_nsIID::PyTypeMethod_dealloc(PyObject *ob)
|
||||
{
|
||||
delete (Py_nsIID *)ob;
|
||||
}
|
||||
127
mozilla/extensions/python/xpcom/src/PyIInputStream.cpp
Normal file
127
mozilla/extensions/python/xpcom/src/PyIInputStream.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written September 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include "nsIInputStream.h"
|
||||
|
||||
// Prevents us needing to use an nsIScriptableInputStream
|
||||
// (and even that can't read binary data!!!)
|
||||
|
||||
static nsIInputStream *GetI(PyObject *self) {
|
||||
nsIID iid = NS_GET_IID(nsIInputStream);
|
||||
|
||||
if (!Py_nsISupports::Check(self, iid)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
|
||||
return NULL;
|
||||
}
|
||||
return (nsIInputStream *)Py_nsISupports::GetI(self);
|
||||
}
|
||||
|
||||
static PyObject *DoPyRead_Buffer(nsIInputStream *pI, PyObject *obBuffer, PRUint32 n)
|
||||
{
|
||||
PRUint32 nread;
|
||||
void *buf;
|
||||
PRUint32 buf_len;
|
||||
if (PyObject_AsWriteBuffer(obBuffer, &buf, (int *)&buf_len) != 0) {
|
||||
PyErr_Clear();
|
||||
PyErr_SetString(PyExc_TypeError, "The buffer object does not have a write buffer!");
|
||||
return NULL;
|
||||
}
|
||||
if (n==(PRUint32)-1) {
|
||||
n = buf_len;
|
||||
} else {
|
||||
if (n > buf_len) {
|
||||
NS_WARNING("Warning: PyIInputStream::read() was passed an integer size greater than the size of the passed buffer! Buffer size used.\n");
|
||||
n = buf_len;
|
||||
}
|
||||
}
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->Read((char *)buf, n, &nread);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return PyInt_FromLong(nread);
|
||||
}
|
||||
|
||||
static PyObject *DoPyRead_Size(nsIInputStream *pI, PRUint32 n)
|
||||
{
|
||||
if (n==-1) {
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->Available(&n);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if (NS_FAILED(r))
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
}
|
||||
char *buf = (char *)nsAllocator::Alloc(n);
|
||||
if (buf==NULL) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
nsresult r;
|
||||
PRUint32 nread;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->Read(buf, n, &nread);
|
||||
Py_END_ALLOW_THREADS;
|
||||
PyObject *rc = NULL;
|
||||
if ( NS_SUCCEEDED(r) ) {
|
||||
rc = PyBuffer_New(nread);
|
||||
if (rc != NULL) {
|
||||
void *ob_buf;
|
||||
PRUint32 buf_len;
|
||||
if (PyObject_AsWriteBuffer(rc, &ob_buf, (int *)&buf_len) != 0) {
|
||||
// should never fail - we just created it!
|
||||
return NULL;
|
||||
}
|
||||
if (buf_len != nread) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "New buffer isnt the size we create it!");
|
||||
return NULL;
|
||||
}
|
||||
memcpy(ob_buf, buf, nread);
|
||||
}
|
||||
} else
|
||||
PyXPCOM_BuildPyException(r);
|
||||
nsAllocator::Free(buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static PyObject *PyRead(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obBuffer = NULL;
|
||||
PRUint32 n = (PRUint32)-1;
|
||||
|
||||
nsIInputStream *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
if (PyArg_ParseTuple(args, "|i", (int *)&n))
|
||||
// This worked - no args, or just an int.
|
||||
return DoPyRead_Size(pI, n);
|
||||
// try our other supported arg format.
|
||||
PyErr_Clear();
|
||||
if (!PyArg_ParseTuple(args, "O|i", &obBuffer, (int *)&n)) {
|
||||
PyErr_Clear();
|
||||
PyErr_SetString(PyExc_TypeError, "'read()' must be called as (buffer_ob, int_size=-1) or (int_size=-1)");
|
||||
return NULL;
|
||||
}
|
||||
return DoPyRead_Buffer(pI, obBuffer, n);
|
||||
}
|
||||
|
||||
|
||||
struct PyMethodDef
|
||||
PyMethods_IInputStream[] =
|
||||
{
|
||||
{ "read", PyRead, 1},
|
||||
// The rest are handled as normal
|
||||
{NULL}
|
||||
};
|
||||
391
mozilla/extensions/python/xpcom/src/PyIInterfaceInfo.cpp
Normal file
391
mozilla/extensions/python/xpcom/src/PyIInterfaceInfo.cpp
Normal file
@@ -0,0 +1,391 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
|
||||
|
||||
static nsIInterfaceInfo *GetI(PyObject *self) {
|
||||
nsIID iid = NS_GET_IID(nsIInterfaceInfo);
|
||||
|
||||
if (!Py_nsISupports::Check(self, iid)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
|
||||
return NULL;
|
||||
}
|
||||
return (nsIInterfaceInfo *)Py_nsISupports::GetI(self);
|
||||
}
|
||||
|
||||
static PyObject *PyGetName(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":GetName"))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
char *name;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetName(&name);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
PyObject *ret = PyString_FromString(name);
|
||||
nsAllocator::Free(name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *PyGetIID(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":GetIID"))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIID *iid_ret;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetIID(&iid_ret);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
PyObject *ret = Py_nsIID::PyObjectFromIID(*iid_ret);
|
||||
nsAllocator::Free(iid_ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *PyIsScriptable(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":IsScriptable"))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
PRBool b_ret;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->IsScriptable(&b_ret);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return PyInt_FromLong(b_ret);
|
||||
}
|
||||
|
||||
static PyObject *PyGetParent(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":GetParent"))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pRet;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetParent(&pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIInterfaceInfo), PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyGetMethodCount(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":GetMethodCount"))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
PRUint16 ret;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetMethodCount(&ret);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return PyInt_FromLong(ret);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *PyGetConstantCount(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":GetConstantCount"))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
PRUint16 ret;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetConstantCount(&ret);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return PyInt_FromLong(ret);
|
||||
}
|
||||
|
||||
static PyObject *PyGetMethodInfo(PyObject *self, PyObject *args)
|
||||
{
|
||||
PRUint16 index;
|
||||
if (!PyArg_ParseTuple(args, "h:GetMethodInfo", &index))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
PRUint16 nmethods;
|
||||
pI->GetMethodCount(&nmethods);
|
||||
if (index>=nmethods) {
|
||||
PyErr_SetString(PyExc_ValueError, "The method index is out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const nsXPTMethodInfo *pRet;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetMethodInfo(index, &pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return PyObject_FromXPTMethodDescriptor(pRet);
|
||||
}
|
||||
|
||||
static PyObject *PyGetMethodInfoForName(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *name;
|
||||
if (!PyArg_ParseTuple(args, "s:GetMethodInfoForName", &name))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
const nsXPTMethodInfo *pRet;
|
||||
PRUint16 index;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetMethodInfoForName(name, &index, &pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
PyObject *ret_i = PyObject_FromXPTMethodDescriptor(pRet);
|
||||
if (ret_i==NULL)
|
||||
return NULL;
|
||||
PyObject *real_ret = Py_BuildValue("iO", (int)index, ret_i);
|
||||
Py_DECREF(ret_i);
|
||||
return real_ret;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *PyGetConstant(PyObject *self, PyObject *args)
|
||||
{
|
||||
PRUint16 index;
|
||||
if (!PyArg_ParseTuple(args, "h:GetConstant", &index))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
const nsXPTConstant *pRet;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetConstant(index, &pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return PyObject_FromXPTConstant(pRet);
|
||||
}
|
||||
|
||||
static PRBool __GetMethodInfoHelper(nsIInterfaceInfo *pii, int mi, int pi, const nsXPTMethodInfo **ppmi)
|
||||
{
|
||||
PRUint16 nmethods=0;
|
||||
pii->GetMethodCount(&nmethods);
|
||||
if (mi<0 || mi>=nmethods) {
|
||||
PyErr_SetString(PyExc_ValueError, "The method index is out of range");
|
||||
return PR_FALSE;
|
||||
}
|
||||
const nsXPTMethodInfo *pmi;
|
||||
nsresult r = pii->GetMethodInfo(mi, &pmi);
|
||||
if ( NS_FAILED(r) ) {
|
||||
PyXPCOM_BuildPyException(r);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
int nparams=0;
|
||||
nparams = pmi->GetParamCount();
|
||||
if (pi<0 || pi>=nparams) {
|
||||
PyErr_SetString(PyExc_ValueError, "The param index is out of range");
|
||||
return PR_FALSE;
|
||||
}
|
||||
*ppmi = pmi;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PyObject *PyGetInfoForParam(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIInterfaceInfo *pii = GetI(self);
|
||||
if (pii==NULL)
|
||||
return NULL;
|
||||
PRUint16 mi, pi;
|
||||
if (!PyArg_ParseTuple(args, "hh:GetInfoForParam", &mi, &pi))
|
||||
return NULL;
|
||||
const nsXPTMethodInfo *pmi;
|
||||
if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
|
||||
return NULL;
|
||||
const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
|
||||
nsIInterfaceInfo *pnewii = nsnull;
|
||||
nsresult n = pii->GetInfoForParam(mi, ¶m_info, &pnewii);
|
||||
if (NS_FAILED(n))
|
||||
return PyXPCOM_BuildPyException(n);
|
||||
return Py_nsISupports::PyObjectFromInterface(pnewii, NS_GET_IID(nsIInterfaceInfo), PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyGetIIDForParam(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIInterfaceInfo *pii = GetI(self);
|
||||
if (pii==NULL)
|
||||
return NULL;
|
||||
PRUint16 mi, pi;
|
||||
if (!PyArg_ParseTuple(args, "hh:GetIIDForParam", &mi, &pi))
|
||||
return NULL;
|
||||
const nsXPTMethodInfo *pmi;
|
||||
if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
|
||||
return NULL;
|
||||
const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
|
||||
nsIID *piid;
|
||||
nsresult n = pii->GetIIDForParam(mi, ¶m_info, &piid);
|
||||
if (NS_FAILED(n) || piid==nsnull)
|
||||
return PyXPCOM_BuildPyException(n);
|
||||
return Py_nsIID::PyObjectFromIID(*piid);
|
||||
}
|
||||
|
||||
static PyObject *PyGetTypeForParam(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIInterfaceInfo *pii = GetI(self);
|
||||
if (pii==NULL)
|
||||
return NULL;
|
||||
PRUint16 mi, pi, dim;
|
||||
if (!PyArg_ParseTuple(args, "hhh:GetTypeForParam", &mi, &pi, &dim))
|
||||
return NULL;
|
||||
const nsXPTMethodInfo *pmi;
|
||||
if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
|
||||
return NULL;
|
||||
nsXPTType datumType;
|
||||
const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
|
||||
nsresult n = pii->GetTypeForParam(mi, ¶m_info, dim, &datumType);
|
||||
if (NS_FAILED(n))
|
||||
return PyXPCOM_BuildPyException(n);
|
||||
return PyObject_FromXPTTypeDescriptor((const XPTTypeDescriptor *)&datumType);
|
||||
}
|
||||
|
||||
static PyObject *PyGetSizeIsArgNumberForParam(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIInterfaceInfo *pii = GetI(self);
|
||||
if (pii==NULL)
|
||||
return NULL;
|
||||
PRUint16 mi, pi, dim;
|
||||
if (!PyArg_ParseTuple(args, "hhh:GetSizeIsArgNumberForParam", &mi, &pi, &dim))
|
||||
return NULL;
|
||||
const nsXPTMethodInfo *pmi;
|
||||
if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
|
||||
return NULL;
|
||||
PRUint8 ret;
|
||||
const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
|
||||
nsresult n = pii->GetSizeIsArgNumberForParam(mi, ¶m_info, dim, &ret);
|
||||
if (NS_FAILED(n))
|
||||
return PyXPCOM_BuildPyException(n);
|
||||
return PyInt_FromLong(ret);
|
||||
}
|
||||
|
||||
static PyObject *PyGetLengthIsArgNumberForParam(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIInterfaceInfo *pii = GetI(self);
|
||||
if (pii==NULL)
|
||||
return NULL;
|
||||
PRUint16 mi, pi, dim;
|
||||
if (!PyArg_ParseTuple(args, "hhh:GetLengthIsArgNumberForParam", &mi, &pi, &dim))
|
||||
return NULL;
|
||||
const nsXPTMethodInfo *pmi;
|
||||
if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
|
||||
return NULL;
|
||||
PRUint8 ret;
|
||||
const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
|
||||
nsresult n = pii->GetLengthIsArgNumberForParam(mi, ¶m_info, dim, &ret);
|
||||
if (NS_FAILED(n))
|
||||
return PyXPCOM_BuildPyException(n);
|
||||
return PyInt_FromLong(ret);
|
||||
}
|
||||
|
||||
static PyObject *PyGetInterfaceIsArgNumberForParam(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIInterfaceInfo *pii = GetI(self);
|
||||
if (pii==NULL)
|
||||
return NULL;
|
||||
PRUint16 mi, pi;
|
||||
if (!PyArg_ParseTuple(args, "hhh:GetInterfaceIsArgNumberForParam", &mi, &pi))
|
||||
return NULL;
|
||||
const nsXPTMethodInfo *pmi;
|
||||
if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
|
||||
return NULL;
|
||||
PRUint8 ret;
|
||||
const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
|
||||
nsresult n = pii->GetInterfaceIsArgNumberForParam(mi, ¶m_info, &ret);
|
||||
if (NS_FAILED(n))
|
||||
return PyXPCOM_BuildPyException(n);
|
||||
return PyInt_FromLong(ret);
|
||||
}
|
||||
|
||||
struct PyMethodDef
|
||||
PyMethods_IInterfaceInfo[] =
|
||||
{
|
||||
{ "GetName", PyGetName, 1},
|
||||
{ "GetIID", PyGetIID, 1},
|
||||
{ "IsScriptable", PyIsScriptable, 1},
|
||||
{ "GetParent", PyGetParent, 1},
|
||||
{ "GetMethodCount", PyGetMethodCount, 1},
|
||||
{ "GetConstantCount", PyGetConstantCount, 1},
|
||||
{ "GetMethodInfo", PyGetMethodInfo, 1},
|
||||
{ "GetMethodInfoForName", PyGetMethodInfoForName, 1},
|
||||
{ "GetConstant", PyGetConstant, 1},
|
||||
{ "GetInfoForParam", PyGetInfoForParam, 1},
|
||||
{ "GetIIDForParam", PyGetIIDForParam, 1},
|
||||
{ "GetTypeForParam", PyGetTypeForParam, 1},
|
||||
{ "GetSizeIsArgNumberForParam", PyGetSizeIsArgNumberForParam, 1},
|
||||
{ "GetLengthIsArgNumberForParam", PyGetLengthIsArgNumberForParam, 1},
|
||||
{ "GetInterfaceIsArgNumberForParam", PyGetInterfaceIsArgNumberForParam, 1},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
/*
|
||||
NS_IMETHOD GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info) = 0;
|
||||
NS_IMETHOD GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info) = 0;
|
||||
NS_IMETHOD GetConstant(PRUint16 index, const nsXPTConstant * *constant) = 0;
|
||||
NS_IMETHOD GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) = 0;
|
||||
NS_IMETHOD GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) = 0;
|
||||
NS_IMETHOD GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval) = 0;
|
||||
NS_IMETHOD GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) = 0;
|
||||
NS_IMETHOD GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) = 0;
|
||||
NS_IMETHOD GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval) = 0;
|
||||
|
||||
*/
|
||||
167
mozilla/extensions/python/xpcom/src/PyIInterfaceInfoManager.cpp
Normal file
167
mozilla/extensions/python/xpcom/src/PyIInterfaceInfoManager.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIInterfaceInfoManager.h>
|
||||
|
||||
static nsIInterfaceInfoManager *GetI(PyObject *self) {
|
||||
nsIID iid = NS_GET_IID(nsIInterfaceInfoManager);
|
||||
|
||||
if (!Py_nsISupports::Check(self, iid)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
|
||||
return NULL;
|
||||
}
|
||||
return (nsIInterfaceInfoManager *)Py_nsISupports::GetI(self);
|
||||
}
|
||||
|
||||
static PyObject *PyGetInfoForIID(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID = NULL;
|
||||
if (!PyArg_ParseTuple(args, "O", &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfoManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pi;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetInfoForIID(&iid, &pi);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
nsIID new_iid = NS_GET_IID(nsIInterfaceInfo);
|
||||
// Can not auto-wrap the interface info manager as it is critical to
|
||||
// building the support we need for autowrap.
|
||||
return Py_nsISupports::PyObjectFromInterface(pi, new_iid, PR_FALSE, PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyGetInfoForName(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *name;
|
||||
if (!PyArg_ParseTuple(args, "s", &name))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfoManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pi;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetInfoForName(name, &pi);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
// Can not auto-wrap the interface info manager as it is critical to
|
||||
// building the support we need for autowrap.
|
||||
return Py_nsISupports::PyObjectFromInterface(pi, NS_GET_IID(nsIInterfaceInfo), PR_FALSE, PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyGetNameForIID(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID = NULL;
|
||||
if (!PyArg_ParseTuple(args, "O", &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfoManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
|
||||
char *ret_name = NULL;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetNameForIID(&iid, &ret_name);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
PyObject *ret = PyString_FromString(ret_name);
|
||||
nsAllocator::Free(ret_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *PyGetIIDForName(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *name;
|
||||
if (!PyArg_ParseTuple(args, "s", &name))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfoManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIID *iid_ret;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetIIDForName(name, &iid_ret);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
PyObject *ret = Py_nsIID::PyObjectFromIID(*iid_ret);
|
||||
nsAllocator::Free(iid_ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *PyEnumerateInterfaces(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfoManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIEnumerator *pRet;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->EnumerateInterfaces(&pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator), PR_FALSE);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// void autoRegisterInterfaces();
|
||||
|
||||
PyMethodDef
|
||||
PyMethods_IInterfaceInfoManager[] =
|
||||
{
|
||||
{ "GetInfoForIID", PyGetInfoForIID, 1},
|
||||
{ "getInfoForIID", PyGetInfoForIID, 1},
|
||||
{ "GetInfoForName", PyGetInfoForName, 1},
|
||||
{ "getInfoForName", PyGetInfoForName, 1},
|
||||
{ "GetIIDForName", PyGetIIDForName, 1},
|
||||
{ "getIIDForName", PyGetIIDForName, 1},
|
||||
{ "GetNameForIID", PyGetNameForIID, 1},
|
||||
{ "getNameForIID", PyGetNameForIID, 1},
|
||||
{ "EnumerateInterfaces", PyEnumerateInterfaces, 1},
|
||||
{ "enumerateInterfaces", PyEnumerateInterfaces, 1},
|
||||
{NULL}
|
||||
};
|
||||
101
mozilla/extensions/python/xpcom/src/PyIServiceManager.cpp
Normal file
101
mozilla/extensions/python/xpcom/src/PyIServiceManager.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIServiceManager.h>
|
||||
|
||||
|
||||
static nsIServiceManager *GetI(PyObject *self) {
|
||||
nsIID iid = NS_GET_IID(nsIServiceManager);
|
||||
|
||||
if (!Py_nsISupports::Check(self, iid)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
|
||||
return NULL;
|
||||
}
|
||||
return (nsIServiceManager *)Py_nsISupports::GetI(self);
|
||||
}
|
||||
|
||||
static PyObject *PyRegisterService(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIServiceManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
PyObject *obCID, *obInterface;
|
||||
if (!PyArg_ParseTuple(args, "OO", &obCID, &obInterface))
|
||||
return NULL;
|
||||
|
||||
nsCOMPtr<nsISupports> pis;
|
||||
if (!Py_nsISupports::InterfaceFromPyObject(obInterface, NS_GET_IID(nsISupports), getter_AddRefs(pis), PR_FALSE))
|
||||
return NULL;
|
||||
nsresult r;
|
||||
if (PyString_Check(obCID) || PyUnicode_Check(obCID)) {
|
||||
const char *val = PyString_AsString(obCID);
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->RegisterService(val, pis);
|
||||
Py_END_ALLOW_THREADS;
|
||||
} else {
|
||||
nsCID cid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obCID, &cid))
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->RegisterService(cid, pis);
|
||||
Py_END_ALLOW_THREADS;
|
||||
}
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *PyGetService(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIServiceManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
PyObject *obIID, *obCID;
|
||||
if (!PyArg_ParseTuple(args, "OO", &obCID, &obIID))
|
||||
return NULL;
|
||||
nsIID cid, iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
|
||||
nsISupports *pis;
|
||||
nsresult r;
|
||||
if (PyString_Check(obCID) || PyUnicode_Check(obCID)) {
|
||||
char *val = PyString_AsString(obCID);
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetService(val, iid, &pis);
|
||||
Py_END_ALLOW_THREADS;
|
||||
} else {
|
||||
if (!Py_nsIID::IIDFromPyObject(obCID, &cid))
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetService(cid, iid, &pis);
|
||||
Py_END_ALLOW_THREADS;
|
||||
}
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE);
|
||||
}
|
||||
|
||||
struct PyMethodDef
|
||||
PyMethods_IServiceManager[] =
|
||||
{
|
||||
{ "GetService", PyGetService, 1},
|
||||
{ "getService", PyGetService, 1},
|
||||
{ "RegisterService", PyRegisterService, 1},
|
||||
{ "registerService", PyRegisterService, 1},
|
||||
{NULL}
|
||||
};
|
||||
165
mozilla/extensions/python/xpcom/src/PyISimpleEnumerator.cpp
Normal file
165
mozilla/extensions/python/xpcom/src/PyISimpleEnumerator.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsISimpleEnumerator.h>
|
||||
|
||||
static nsISimpleEnumerator *GetI(PyObject *self) {
|
||||
nsIID iid = NS_GET_IID(nsISimpleEnumerator);
|
||||
|
||||
if (!Py_nsISupports::Check(self, iid)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
|
||||
return NULL;
|
||||
}
|
||||
return (nsISimpleEnumerator *)Py_nsISupports::GetI(self);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *PyHasMoreElements(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":HasMoreElements"))
|
||||
return NULL;
|
||||
|
||||
nsISimpleEnumerator *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsresult r;
|
||||
PRBool more;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->HasMoreElements(&more);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return PyInt_FromLong(more);
|
||||
}
|
||||
|
||||
static PyObject *PyGetNext(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID = NULL;
|
||||
if (!PyArg_ParseTuple(args, "|O:GetNext", &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIID iid(NS_GET_IID(nsISupports));
|
||||
if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
nsISimpleEnumerator *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsISupports *pRet = nsnull;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetNext(&pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
if (obIID) {
|
||||
nsISupports *temp;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pRet->QueryInterface(iid, (void **)&temp);
|
||||
pRet->Release();
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) ) {
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
}
|
||||
pRet = temp;
|
||||
}
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, iid, PR_FALSE);
|
||||
}
|
||||
|
||||
// A method added for Python performance if you really need
|
||||
// it. Allows you to fetch a block of objects in one
|
||||
// hit, allowing the loop to remain implemented in C.
|
||||
static PyObject *PyFetchBlock(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID = NULL;
|
||||
int n_wanted;
|
||||
int n_fetched = 0;
|
||||
if (!PyArg_ParseTuple(args, "i|O:FetchBlock", &n_wanted, &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIID iid(NS_GET_IID(nsISupports));
|
||||
if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
nsISimpleEnumerator *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
// We want to fetch with the thread-lock released,
|
||||
// but this means we can not append to the PyList
|
||||
nsISupports **fetched = new nsISupports*[n_wanted];
|
||||
if (fetched==nsnull) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
memset(fetched, 0, sizeof(nsISupports *) * n_wanted);
|
||||
nsresult r;
|
||||
PRBool more;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
for (;n_fetched<n_wanted;) {
|
||||
r = pI->HasMoreElements(&more);
|
||||
if (NS_FAILED(r))
|
||||
break; // this _is_ an error!
|
||||
if (!more)
|
||||
break; // Normal enum end.
|
||||
nsISupports *pNew;
|
||||
r = pI->GetNext(&pNew);
|
||||
if (NS_FAILED(r)) // IS an error
|
||||
break;
|
||||
if (obIID) {
|
||||
nsISupports *temp;
|
||||
r = pNew->QueryInterface(iid, (void **)&temp);
|
||||
pNew->Release();
|
||||
if ( NS_FAILED(r) ) {
|
||||
break;
|
||||
}
|
||||
pNew = temp;
|
||||
}
|
||||
fetched[n_fetched] = pNew;
|
||||
n_fetched++;
|
||||
}
|
||||
Py_END_ALLOW_THREADS;
|
||||
PyObject *ret;
|
||||
if (NS_SUCCEEDED(r)) {
|
||||
ret = PyList_New(n_fetched);
|
||||
if (ret)
|
||||
for (int i=0;i<n_fetched;i++) {
|
||||
PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid, PR_FALSE);
|
||||
PyList_SET_ITEM(ret, i, new_ob);
|
||||
}
|
||||
} else
|
||||
ret = PyXPCOM_BuildPyException(r);
|
||||
|
||||
if ( ret == NULL ) {
|
||||
// Free the objects we consumed.
|
||||
for (int i=0;i<n_fetched;i++)
|
||||
fetched[i]->Release();
|
||||
|
||||
}
|
||||
delete [] fetched;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct PyMethodDef
|
||||
PyMethods_ISimpleEnumerator[] =
|
||||
{
|
||||
{ "HasMoreElements", PyHasMoreElements, 1},
|
||||
{ "hasMoreElements", PyHasMoreElements, 1},
|
||||
{ "GetNext", PyGetNext, 1},
|
||||
{ "getNext", PyGetNext, 1},
|
||||
{ "FetchBlock", PyFetchBlock, 1},
|
||||
{ "fetchBlock", PyFetchBlock, 1},
|
||||
{NULL}
|
||||
};
|
||||
343
mozilla/extensions/python/xpcom/src/PyISupports.cpp
Normal file
343
mozilla/extensions/python/xpcom/src/PyISupports.cpp
Normal file
@@ -0,0 +1,343 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
|
||||
static PRInt32 cInterfaces=0;
|
||||
static PyObject *g_obFuncMakeInterfaceCount = NULL; // XXX - never released!!!
|
||||
|
||||
PRInt32
|
||||
_PyXPCOM_GetInterfaceCount(void)
|
||||
{
|
||||
return cInterfaces;
|
||||
}
|
||||
|
||||
Py_nsISupports::Py_nsISupports(nsISupports *punk, const nsIID &iid, PyTypeObject *this_type)
|
||||
{
|
||||
ob_type = this_type;
|
||||
m_obj = punk;
|
||||
m_iid = iid;
|
||||
// refcnt of object managed by caller.
|
||||
PR_AtomicIncrement(&cInterfaces);
|
||||
PyXPCOM_DLLAddRef();
|
||||
_Py_NewReference(this);
|
||||
}
|
||||
|
||||
Py_nsISupports::~Py_nsISupports()
|
||||
{
|
||||
SafeRelease(this);
|
||||
PR_AtomicDecrement(&cInterfaces);
|
||||
PyXPCOM_DLLRelease();
|
||||
}
|
||||
|
||||
/*static*/ nsISupports *
|
||||
Py_nsISupports::GetI(PyObject *self, nsIID *ret_iid)
|
||||
{
|
||||
if (self==NULL) {
|
||||
PyErr_SetString(PyExc_ValueError, "The Python object is invalid");
|
||||
return NULL;
|
||||
}
|
||||
Py_nsISupports *pis = (Py_nsISupports *)self;
|
||||
if (pis->m_obj==NULL) {
|
||||
// This should never be able to happen.
|
||||
PyErr_SetString(PyExc_ValueError, "Internal Error - The XPCOM object has been released.");
|
||||
return NULL;
|
||||
}
|
||||
if (ret_iid)
|
||||
*ret_iid = pis->m_iid;
|
||||
return pis->m_obj;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
Py_nsISupports::SafeRelease(Py_nsISupports *ob)
|
||||
{
|
||||
if (!ob)
|
||||
return;
|
||||
if (ob->m_obj)
|
||||
{
|
||||
long rcnt;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
rcnt = ob->m_obj->Release();
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
#ifdef _DEBUG_LIFETIMES
|
||||
LogF(buf, " SafeRelease(%ld) -> %s at 0x%0lx, nsISupports at 0x%0lx - Release() returned %ld",GetCurrentThreadId(), ob->ob_type->tp_name,ob, ob->m_obj,rcnt);
|
||||
#endif
|
||||
ob->m_obj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ Py_nsISupports *
|
||||
Py_nsISupports::Constructor(nsISupports *pInitObj, const nsIID &iid)
|
||||
{
|
||||
return new Py_nsISupports(pInitObj,
|
||||
iid,
|
||||
type);
|
||||
}
|
||||
|
||||
/*static*/PRBool
|
||||
Py_nsISupports::InterfaceFromPyObject(PyObject *ob,
|
||||
const nsIID &iid,
|
||||
nsISupports **ppv,
|
||||
PRBool bNoneOK,
|
||||
PRBool bTryAutoWrap /* = PR_TRUE */)
|
||||
{
|
||||
if ( ob == NULL )
|
||||
{
|
||||
// don't overwrite an error message
|
||||
if ( !PyErr_Occurred() )
|
||||
PyErr_SetString(PyExc_TypeError, "The Python object is invalid");
|
||||
return PR_FALSE;
|
||||
}
|
||||
if ( ob == Py_None )
|
||||
{
|
||||
if ( bNoneOK )
|
||||
{
|
||||
*ppv = NULL;
|
||||
return PR_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "None is not a invalid interface object in this context");
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (PyInstance_Check(ob)) {
|
||||
// Get the _comobj_ attribute
|
||||
PyObject *use_ob = PyObject_GetAttrString(ob, "_comobj_");
|
||||
if (use_ob==NULL) {
|
||||
PyErr_Clear();
|
||||
if (bTryAutoWrap)
|
||||
// Try and auto-wrap it - errors will leave Py exception set,
|
||||
return PyXPCOM_XPTStub::AutoWrapPythonInstance(ob, iid, ppv);
|
||||
PyErr_SetString(PyExc_TypeError, "The Python instance can not be converted to an XP COM object");
|
||||
return PR_FALSE;
|
||||
} else
|
||||
ob = use_ob;
|
||||
|
||||
} else {
|
||||
Py_XINCREF(ob);
|
||||
}
|
||||
|
||||
nsISupports *pis;
|
||||
PRBool rc = PR_FALSE;
|
||||
if ( !Check(ob) )
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be used as COM objects", ob->ob_type->tp_name);
|
||||
goto done;
|
||||
}
|
||||
nsIID already_iid;
|
||||
pis = GetI(ob, &already_iid);
|
||||
if ( !pis )
|
||||
goto done; /* exception was set by GetI() */
|
||||
/* note: we don't (yet) explicitly hold a reference to pis */
|
||||
if (iid.Equals(Py_nsIID_NULL)) {
|
||||
// a bit of a hack - we are asking for the arbitary interface
|
||||
// wrapped by this object, not some other specific interface -
|
||||
// so no QI, just an AddRef();
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
pis->AddRef();
|
||||
Py_END_ALLOW_THREADS
|
||||
*ppv = pis;
|
||||
} else {
|
||||
// specific interface requested - if it is not already the
|
||||
// specific interface, QI for it and discard pis.
|
||||
if (iid.Equals(already_iid)) {
|
||||
*ppv = pis;
|
||||
pis->AddRef();
|
||||
} else {
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
r = pis->QueryInterface(iid, (void **)ppv);
|
||||
Py_END_ALLOW_THREADS
|
||||
if ( NS_FAILED(r) )
|
||||
{
|
||||
PyXPCOM_BuildPyException(r);
|
||||
goto done;
|
||||
}
|
||||
/* note: the QI added a ref for the return value */
|
||||
}
|
||||
}
|
||||
|
||||
rc = PR_TRUE;
|
||||
done:
|
||||
Py_XDECREF(ob);
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Interface conversions
|
||||
/*static*/void
|
||||
Py_nsISupports::RegisterInterface( const nsIID &iid, PyTypeObject *t)
|
||||
{
|
||||
if (mapIIDToType==NULL)
|
||||
mapIIDToType = PyDict_New();
|
||||
|
||||
if (mapIIDToType) {
|
||||
PyObject *key = Py_nsIID::PyObjectFromIID(iid);
|
||||
if (key)
|
||||
PyDict_SetItem(mapIIDToType, key, (PyObject *)t);
|
||||
Py_XDECREF(key);
|
||||
}
|
||||
}
|
||||
|
||||
/*static */PyObject *
|
||||
Py_nsISupports::PyObjectFromInterface(nsISupports *pis,
|
||||
const nsIID &riid,
|
||||
PRBool bAddRef,
|
||||
PRBool bMakeNicePyObject /* = PR_TRUE */)
|
||||
{
|
||||
// Quick exit.
|
||||
if (pis==NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
PyTypeObject *createType = NULL;
|
||||
// If the IID is for nsISupports, dont bother with
|
||||
// a map lookup as we know the type!
|
||||
if (!riid.Equals(NS_GET_IID(nsISupports))) {
|
||||
|
||||
// Look up the map
|
||||
PyObject *obiid = Py_nsIID::PyObjectFromIID(riid);
|
||||
if (!obiid) return NULL;
|
||||
|
||||
if (mapIIDToType != NULL)
|
||||
createType = (PyTypeObject *)PyDict_GetItem(mapIIDToType, obiid);
|
||||
Py_DECREF(obiid);
|
||||
}
|
||||
if (createType==NULL)
|
||||
createType = Py_nsISupports::type;
|
||||
// Check it is indeed one of our types.
|
||||
if (!PyXPCOM_TypeObject::IsType(createType)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "The type map is invalid");
|
||||
return NULL;
|
||||
}
|
||||
// we can now safely cast the thing to a PyComTypeObject and use it
|
||||
PyXPCOM_TypeObject *myCreateType = (PyXPCOM_TypeObject *)createType;
|
||||
if (myCreateType->ctor==NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "The type does not declare a PyCom constructor");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_nsISupports *ret = (*myCreateType->ctor)(pis, riid);
|
||||
#ifdef _DEBUG_LIFETIMES
|
||||
PyXPCOM_LogF("XPCOM Object created at 0x%0xld, nsISupports at 0x%0xld",
|
||||
ret, ret->m_obj);
|
||||
#endif
|
||||
if (ret && bAddRef && pis) pis->AddRef();
|
||||
if (ret && bMakeNicePyObject)
|
||||
return MakeInterfaceResult(ret, riid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Call back into Python, passing a raw nsIInterface object, getting back
|
||||
// the object to actually pass to Python.
|
||||
PyObject *
|
||||
Py_nsISupports::MakeInterfaceResult(PyObject *pyis,
|
||||
const nsIID &iid)
|
||||
{
|
||||
NS_PRECONDITION(pyis, "NULL pyobject!");
|
||||
PyObject *obIID = NULL;
|
||||
PyObject *args = NULL;
|
||||
PyObject *func = NULL;
|
||||
PyObject *mod = NULL;
|
||||
PyObject *ret = NULL;
|
||||
|
||||
obIID = Py_nsIID::PyObjectFromIID(iid);
|
||||
if (obIID==NULL)
|
||||
goto done;
|
||||
|
||||
if (g_obFuncMakeInterfaceCount==NULL) {
|
||||
PyObject *mod = PyImport_ImportModule("xpcom.client");
|
||||
if (mod)
|
||||
g_obFuncMakeInterfaceCount = PyObject_GetAttrString(mod, "MakeInterfaceResult");
|
||||
Py_XDECREF(mod);
|
||||
}
|
||||
if (g_obFuncMakeInterfaceCount==NULL) goto done;
|
||||
|
||||
args = Py_BuildValue("OO", pyis, obIID);
|
||||
if (args==NULL) goto done;
|
||||
ret = PyEval_CallObject(g_obFuncMakeInterfaceCount, args);
|
||||
done:
|
||||
if (PyErr_Occurred()) {
|
||||
NS_ABORT_IF_FALSE(ret==NULL, "Have an error, but also a return val!");
|
||||
PyXPCOM_LogError("Creating an interface object to be used as a parameter failed\n");
|
||||
PyErr_Clear();
|
||||
}
|
||||
Py_XDECREF(mod);
|
||||
Py_XDECREF(args);
|
||||
Py_XDECREF(obIID);
|
||||
if (ret==NULL) // eek - error - return the original with no refcount mod.
|
||||
ret = pyis;
|
||||
else
|
||||
// no error - decref the old object
|
||||
Py_DECREF(pyis);
|
||||
// return our obISupports. If NULL, we are really hosed and nothing we can do.
|
||||
return ret;
|
||||
}
|
||||
|
||||
// @pymethod <o Py_nsISupports>|Py_nsISupports|QueryInterface|Queries an object for a specific interface.
|
||||
PyObject *
|
||||
Py_nsISupports::QueryInterface(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obiid;
|
||||
int bWrap = 1;
|
||||
// @pyparm IID|iid||The IID requested.
|
||||
// @rdesc The result is always a <o Py_nsISupports> object.
|
||||
// Any error (including E_NOINTERFACE) will generate a <o com_error> exception.
|
||||
if (!PyArg_ParseTuple(args, "O|i:QueryInterface", &obiid, &bWrap))
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obiid, &iid))
|
||||
return NULL;
|
||||
|
||||
nsISupports *pMyIS = GetI(self);
|
||||
if (pMyIS==NULL) return NULL;
|
||||
|
||||
nsISupports *pis;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pMyIS->QueryInterface(iid, (void **)&pis);
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
/* Note that this failure may include E_NOINTERFACE */
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
return PyObjectFromInterface(pis, iid, PR_FALSE, (PRBool)bWrap);
|
||||
}
|
||||
|
||||
|
||||
// @object Py_nsISupports|The base object for all PythonCOM objects. Wraps a COM nsISupports interface.
|
||||
/*static*/ struct PyMethodDef
|
||||
Py_nsISupports::methods[] =
|
||||
{
|
||||
{ "queryInterface", Py_nsISupports::QueryInterface, 1, "Queries the object for an interface."},
|
||||
{ "QueryInterface", Py_nsISupports::QueryInterface, 1, "An alias for queryInterface."},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
/*static*/void Py_nsISupports::InitType(void)
|
||||
{
|
||||
type = new PyXPCOM_TypeObject(
|
||||
"nsISupports",
|
||||
NULL,
|
||||
sizeof(Py_nsISupports),
|
||||
methods,
|
||||
Constructor);
|
||||
}
|
||||
|
||||
PyXPCOM_TypeObject *Py_nsISupports::type = NULL;
|
||||
PyObject *Py_nsISupports::mapIIDToType = NULL;
|
||||
557
mozilla/extensions/python/xpcom/src/PyXPCOM.h
Normal file
557
mozilla/extensions/python/xpcom/src/PyXPCOM.h
Normal file
@@ -0,0 +1,557 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// PyXPCOM.h - the main header file for the Python XPCOM support.
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#ifndef __PYXPCOM_H__
|
||||
#define __PYXPCOM_H__
|
||||
|
||||
#ifdef XP_WIN
|
||||
# ifdef BUILD_PYXPCOM
|
||||
/* We are building the main dll */
|
||||
# define PYXPCOM_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
/* This module uses the dll */
|
||||
# define PYXPCOM_EXPORT __declspec(dllimport)
|
||||
# endif // BUILD_PYXPCOM
|
||||
|
||||
// We need these libs!
|
||||
# pragma comment(lib, "xpcom.lib")
|
||||
# pragma comment(lib, "nspr4.lib")
|
||||
|
||||
#else // XP_WIN
|
||||
# define PYXPCOM_EXPORT
|
||||
#endif // XP_WIN
|
||||
|
||||
|
||||
// An IID we treat as NULL when passing as a reference.
|
||||
extern nsIID Py_nsIID_NULL;
|
||||
|
||||
/*************************************************************************
|
||||
**************************************************************************
|
||||
|
||||
Error and exception related function.
|
||||
|
||||
**************************************************************************
|
||||
*************************************************************************/
|
||||
|
||||
// The exception object (loaded from the xpcom .py code)
|
||||
extern PYXPCOM_EXPORT PyObject *PyXPCOM_Error;
|
||||
|
||||
// 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 PyXPCOM_BuildPyException(hr, punk, IID_IWhatever)"
|
||||
PYXPCOM_EXPORT PyObject *PyXPCOM_BuildPyException(nsresult res);
|
||||
|
||||
// Used in gateways to handle the current Python exception
|
||||
// NOTE: this function assumes it is operating within the Python context
|
||||
PYXPCOM_EXPORT nsresult PyXPCOM_SetCOMErrorFromPyException();
|
||||
|
||||
// A couple of logging/error functions. These probably end up
|
||||
// being written to the console service.
|
||||
|
||||
// Log a warning for the user - something at runtime
|
||||
// they may care about, but nothing that prevents us actually
|
||||
// working.
|
||||
// As it's designed for user error/warning, it exists in non-debug builds.
|
||||
PYXPCOM_EXPORT void PyXPCOM_LogWarning(const char *fmt, ...);
|
||||
|
||||
// Log an error for the user - something that _has_ prevented
|
||||
// us working. This is probably accompanied by a traceback.
|
||||
// As it's designed for user error/warning, it exists in non-debug builds.
|
||||
PYXPCOM_EXPORT void PyXPCOM_LogError(const char *fmt, ...);
|
||||
|
||||
#ifdef DEBUG
|
||||
// Mainly designed for developers of the XPCOM package.
|
||||
// Only enabled in debug builds.
|
||||
PYXPCOM_EXPORT void PyXPCOM_LogDebug(const char *fmt, ...);
|
||||
#define PYXPCOM_LOG_DEBUG PyXPCOM_LogDebug
|
||||
#else
|
||||
#define PYXPCOM_LOG_DEBUG()
|
||||
#endif // DEBUG
|
||||
|
||||
/*************************************************************************
|
||||
**************************************************************************
|
||||
|
||||
Support for CALLING (ie, using) interfaces.
|
||||
|
||||
**************************************************************************
|
||||
*************************************************************************/
|
||||
|
||||
class Py_nsISupports;
|
||||
|
||||
typedef Py_nsISupports* (* PyXPCOM_I_CTOR)(nsISupports *, const nsIID &);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// class PyXPCOM_TypeObject
|
||||
// Base class for (most of) the type objects.
|
||||
|
||||
class PYXPCOM_EXPORT PyXPCOM_TypeObject : public PyTypeObject {
|
||||
public:
|
||||
PyXPCOM_TypeObject(
|
||||
const char *name,
|
||||
PyXPCOM_TypeObject *pBaseType,
|
||||
int typeSize,
|
||||
struct PyMethodDef* methodList,
|
||||
PyXPCOM_I_CTOR ctor);
|
||||
~PyXPCOM_TypeObject();
|
||||
|
||||
PyMethodChain chain;
|
||||
PyXPCOM_TypeObject *baseType;
|
||||
PyXPCOM_I_CTOR ctor;
|
||||
|
||||
static PRBool IsType(PyTypeObject *t);
|
||||
// Static methods for the Python type.
|
||||
static void Py_dealloc(PyObject *ob);
|
||||
static PyObject *Py_repr(PyObject *ob);
|
||||
static PyObject *Py_str(PyObject *ob);
|
||||
static PyObject *Py_getattr(PyObject *self, char *name);
|
||||
static int Py_setattr(PyObject *op, char *name, PyObject *v);
|
||||
static int Py_cmp(PyObject *ob1, PyObject *ob2);
|
||||
static long Py_hash(PyObject *self);
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// class Py_nsISupports
|
||||
// This class serves 2 purposes:
|
||||
// * It is a base class for other interfaces we support "natively"
|
||||
// * It is instantiated for _all_ other interfaces.
|
||||
//
|
||||
// This is different than win32com, where a PyIUnknown only
|
||||
// ever holds an IUnknown - but here, we could be holding
|
||||
// _any_ interface.
|
||||
class PYXPCOM_EXPORT Py_nsISupports : public PyObject
|
||||
{
|
||||
public:
|
||||
static PRBool Check( PyObject *ob, const nsIID &checkIID = Py_nsIID_NULL) {
|
||||
Py_nsISupports *self = static_cast<Py_nsISupports *>(ob);
|
||||
if (ob==NULL || !PyXPCOM_TypeObject::IsType(ob->ob_type ))
|
||||
return PR_FALSE;
|
||||
if (!checkIID.Equals(Py_nsIID_NULL))
|
||||
return self->m_iid.Equals(checkIID) != 0;
|
||||
return PR_TRUE;
|
||||
}
|
||||
// Get the nsISupports interface from the PyObject WITH NO REF COUNT ADDED
|
||||
static nsISupports *GetI(PyObject *self, nsIID *ret_iid = NULL);
|
||||
nsISupports *m_obj;
|
||||
nsIID m_iid;
|
||||
|
||||
// Given an nsISupports and an Interface ID, create and return an object
|
||||
// Does not QI the object - the caller must ensure the nsISupports object
|
||||
// is really a pointer to an object identified by the IID.
|
||||
// PRBool bAddRef indicates if a COM reference count should be added to the interface.
|
||||
// This depends purely on the context in which it is called. If the interface is obtained
|
||||
// from a function that creates a new ref (eg, ???) 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. ***
|
||||
// PRBool bMakeNicePyObject indicates if we should call back into
|
||||
// Python to wrap the object. This allows Python code to
|
||||
// see the correct xpcom.client.Interface object even when calling
|
||||
// xpcom function directly.
|
||||
static PyObject *PyObjectFromInterface(nsISupports *ps,
|
||||
const nsIID &iid,
|
||||
PRBool bAddRef,
|
||||
PRBool bMakeNicePyObject = PR_TRUE);
|
||||
|
||||
// Given a Python object that is a registered COM type, return a given
|
||||
// interface pointer on its underlying object, with a NEW REFERENCE ADDED.
|
||||
// bTryAutoWrap indicates if a Python instance object should attempt to
|
||||
// be automatically wrapped in an XPCOM object. This is really only
|
||||
// provided to stop accidental recursion should the object returned by
|
||||
// the wrap process itself be in instance (where it should already be
|
||||
// a COM object.
|
||||
static PRBool InterfaceFromPyObject(
|
||||
PyObject *ob,
|
||||
const nsIID &iid,
|
||||
nsISupports **ppret,
|
||||
PRBool bNoneOK,
|
||||
PRBool bTryAutoWrap = PR_TRUE);
|
||||
|
||||
static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid);
|
||||
// The Python methods
|
||||
static PyObject *QueryInterface(PyObject *self, PyObject *args);
|
||||
|
||||
// Internal (sort-of) objects.
|
||||
static PyXPCOM_TypeObject *type;
|
||||
static PyMethodDef methods[];
|
||||
static PyObject *mapIIDToType;
|
||||
static void SafeRelease(Py_nsISupports *ob);
|
||||
static void RegisterInterface( const nsIID &iid, PyTypeObject *t);
|
||||
static void InitType();
|
||||
|
||||
~Py_nsISupports();
|
||||
protected:
|
||||
// ctor is protected - must create objects via
|
||||
// PyObjectFromInterface()
|
||||
Py_nsISupports(nsISupports *p,
|
||||
const nsIID &iid,
|
||||
PyTypeObject *type);
|
||||
|
||||
static PyObject *MakeInterfaceResult(PyObject *pyis, const nsIID &iid);
|
||||
|
||||
};
|
||||
|
||||
// Python/XPCOM IID support
|
||||
class PYXPCOM_EXPORT Py_nsIID : public PyObject
|
||||
{
|
||||
public:
|
||||
Py_nsIID(const nsIID &riid);
|
||||
nsIID m_iid;
|
||||
|
||||
PRBool
|
||||
IsEqual(const nsIID &riid) {
|
||||
return m_iid.Equals(riid);
|
||||
}
|
||||
|
||||
PRBool
|
||||
IsEqual(PyObject *ob) {
|
||||
return ob &&
|
||||
ob->ob_type== &type &&
|
||||
m_iid.Equals(((Py_nsIID *)ob)->m_iid);
|
||||
}
|
||||
|
||||
PRBool
|
||||
IsEqual(Py_nsIID &iid) {
|
||||
return m_iid.Equals(iid.m_iid);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyObjectFromIID(const nsIID &iid) {
|
||||
return new Py_nsIID(iid);
|
||||
}
|
||||
|
||||
static PRBool IIDFromPyObject(PyObject *ob, nsIID *pRet);
|
||||
/* Python support */
|
||||
static PyObject *PyTypeMethod_getattr(PyObject *self, char *name);
|
||||
static int PyTypeMethod_compare(PyObject *self, PyObject *ob);
|
||||
static PyObject *PyTypeMethod_repr(PyObject *self);
|
||||
static long PyTypeMethod_hash(PyObject *self);
|
||||
static PyObject *PyTypeMethod_str(PyObject *self);
|
||||
static void PyTypeMethod_dealloc(PyObject *self);
|
||||
static PyTypeObject type;
|
||||
static PyMethodDef methods[];
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// Helper classes for managing arrays of variants.
|
||||
class PythonTypeDescriptor; // Forward declare.
|
||||
|
||||
class PYXPCOM_EXPORT PyXPCOM_InterfaceVariantHelper {
|
||||
public:
|
||||
PyXPCOM_InterfaceVariantHelper();
|
||||
~PyXPCOM_InterfaceVariantHelper();
|
||||
PRBool Init(PyObject *obParams);
|
||||
PRBool FillArray();
|
||||
|
||||
PyObject *MakePythonResult();
|
||||
|
||||
nsXPTCVariant *m_var_array;
|
||||
int m_num_array;
|
||||
protected:
|
||||
PyObject *MakeSinglePythonResult(int index);
|
||||
PRBool FillInVariant(const PythonTypeDescriptor &, int, int);
|
||||
PRBool PrepareOutVariant(const PythonTypeDescriptor &td, int value_index);
|
||||
PRBool SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size);
|
||||
PRUint32 GetSizeIs( int var_index, PRBool is_arg1);
|
||||
|
||||
PyObject *m_pyparams; // sequence of actual params passed (ie, not including hidden)
|
||||
PyObject *m_typedescs; // desc of _all_ params, including hidden.
|
||||
PythonTypeDescriptor *m_python_type_desc_array;
|
||||
void **m_buffer_array;
|
||||
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
**************************************************************************
|
||||
|
||||
Support for IMPLEMENTING interfaces.
|
||||
|
||||
**************************************************************************
|
||||
*************************************************************************/
|
||||
#define NS_IINTERNALPYTHON_IID_STR "AC7459FC-E8AB-4f2e-9C4F-ADDC53393A20"
|
||||
#define NS_IINTERNALPYTHON_IID \
|
||||
{ 0xac7459fc, 0xe8ab, 0x4f2e, { 0x9c, 0x4f, 0xad, 0xdc, 0x53, 0x39, 0x3a, 0x20 } }
|
||||
|
||||
class PyXPCOM_GatewayWeakReference;
|
||||
|
||||
// This interface is needed primarily to give us a known vtable base.
|
||||
// If we QI a Python object for this interface, we can safely cast the result
|
||||
// to a PyG_Base. Any other interface, we do now know which vtable we will get.
|
||||
// Later, we may get some internal functions
|
||||
// (eg, win32com allows us to get the underlying Python object, but
|
||||
// we should try and avoid that if possible.
|
||||
class nsIInternalPython : public nsISupports {
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IINTERNALPYTHON_IID)
|
||||
};
|
||||
|
||||
// This is roughly equivilent to PyGatewayBase in win32com
|
||||
//
|
||||
class PYXPCOM_EXPORT PyG_Base : public nsIInternalPython, public nsISupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISUPPORTSWEAKREFERENCE
|
||||
|
||||
// A static "constructor" - the real ctor is protected.
|
||||
static nsresult CreateNew(PyObject *pPyInstance,
|
||||
const nsIID &iid,
|
||||
void **ppResult);
|
||||
|
||||
// A utility to auto-wrap an arbitary Python instance
|
||||
// in a COM gateway.
|
||||
static PRBool AutoWrapPythonInstance(PyObject *ob,
|
||||
const nsIID &iid,
|
||||
nsISupports **ppret);
|
||||
|
||||
|
||||
// A helper that creates objects to be passed for nsISupports
|
||||
// objects. See extensive comments in PyG_Base.cpp.
|
||||
PyObject *MakeInterfaceParam(nsISupports *pis,
|
||||
const nsIID *piid,
|
||||
int methodIndex = -1,
|
||||
const XPTParamDescriptor *d = NULL,
|
||||
int paramIndex = -1);
|
||||
|
||||
// A helper that ensures all casting and vtable offsetting etc
|
||||
// done against this object happens in the one spot!
|
||||
virtual void *ThisAsIID( const nsIID &iid ) = 0;
|
||||
|
||||
// Helpers for "native" interfaces.
|
||||
// Not used by the generic stub interface.
|
||||
nsresult HandleNativeGatewayError(const char *szMethodName);
|
||||
// These data members used by the converter helper functions - hence public
|
||||
nsIID m_iid;
|
||||
PyObject * m_pPyObject;
|
||||
// We keep a reference count on this object, and the object
|
||||
// itself uses normal refcount rules - thus, it will only
|
||||
// die when we die, and all external references are removed.
|
||||
// This means that once we have created it (and while we
|
||||
// are alive) it will never die.
|
||||
nsCOMPtr<nsIWeakReference> m_pWeakRef;
|
||||
protected:
|
||||
PyG_Base(PyObject *instance, const nsIID &iid);
|
||||
virtual ~PyG_Base();
|
||||
PyG_Base *m_pBaseObject; // A chain to implement identity rules.
|
||||
nsresult InvokeNativeViaPolicy( const char *szMethodName,
|
||||
PyObject **ppResult = NULL,
|
||||
const char *szFormat = NULL,
|
||||
...
|
||||
);
|
||||
nsresult InvokeNativeViaPolicyInternal( const char *szMethodName,
|
||||
PyObject **ppResult,
|
||||
const char *szFormat,
|
||||
va_list va);
|
||||
nsresult InvokeNativeGetViaPolicy(const char *szPropertyName,
|
||||
PyObject **ppResult = NULL
|
||||
);
|
||||
nsresult InvokeNativeSetViaPolicy(const char *szPropertyName,
|
||||
...);
|
||||
};
|
||||
|
||||
class PYXPCOM_EXPORT PyXPCOM_XPTStub : public PyG_Base, public nsXPTCStubBase
|
||||
{
|
||||
friend class PyG_Base;
|
||||
public:
|
||||
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) \
|
||||
{return PyG_Base::QueryInterface(aIID, aInstancePtr);} \
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void) {return PyG_Base::AddRef();} \
|
||||
NS_IMETHOD_(nsrefcnt) Release(void) {return PyG_Base::Release();} \
|
||||
|
||||
NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info);
|
||||
// call this method and return result
|
||||
NS_IMETHOD CallMethod(PRUint16 methodIndex,
|
||||
const nsXPTMethodInfo* info,
|
||||
nsXPTCMiniVariant* params);
|
||||
|
||||
virtual void *ThisAsIID(const nsIID &iid);
|
||||
protected:
|
||||
PyXPCOM_XPTStub(PyObject *instance, const nsIID &iid) : PyG_Base(instance, iid) {;}
|
||||
private:
|
||||
};
|
||||
|
||||
// For the Gateways me manually implement.
|
||||
#define PYGATEWAY_BASE_SUPPORT(INTERFACE, GATEWAY_BASE) \
|
||||
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) \
|
||||
{return PyG_Base::QueryInterface(aIID, aInstancePtr);} \
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void) {return PyG_Base::AddRef();} \
|
||||
NS_IMETHOD_(nsrefcnt) Release(void) {return PyG_Base::Release();} \
|
||||
virtual void *ThisAsIID(const nsIID &iid) { \
|
||||
if (iid.Equals(NS_GET_IID(INTERFACE))) return (INTERFACE *)this; \
|
||||
return GATEWAY_BASE::ThisAsIID(iid); \
|
||||
} \
|
||||
|
||||
|
||||
// Weak Reference class. This is a true COM object, representing
|
||||
// a weak reference to a Python object. For each Python XPCOM object,
|
||||
// there is exactly zero or one corresponding weak reference instance.
|
||||
// When both are alive, each holds a pointer to the other. When the main
|
||||
// object dies due to XPCOM reference counting, it zaps the pointer
|
||||
// in its corresponding weak reference object. Thus, the weak-reference
|
||||
// can live beyond the object (possibly with a NULL pointer back to the
|
||||
// "real" object, but as implemented, the weak reference will never be
|
||||
// destroyed before the object
|
||||
class PYXPCOM_EXPORT PyXPCOM_GatewayWeakReference : public nsIWeakReference {
|
||||
public:
|
||||
PyXPCOM_GatewayWeakReference(PyG_Base *base);
|
||||
~PyXPCOM_GatewayWeakReference();
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEAKREFERENCE;
|
||||
PyG_Base *m_pBase; // NO REF COUNT!!!
|
||||
};
|
||||
|
||||
|
||||
// Helpers classes for our gateways.
|
||||
class PYXPCOM_EXPORT PyXPCOM_GatewayVariantHelper
|
||||
{
|
||||
public:
|
||||
PyXPCOM_GatewayVariantHelper( PyG_Base *gateway,
|
||||
int methodIndex,
|
||||
const nsXPTMethodInfo *info,
|
||||
nsXPTCMiniVariant* params );
|
||||
~PyXPCOM_GatewayVariantHelper();
|
||||
PyObject *MakePyArgs();
|
||||
nsresult ProcessPythonResult(PyObject *ob);
|
||||
PyG_Base *m_gateway;
|
||||
private:
|
||||
nsresult BackFillVariant( PyObject *ob, int index);
|
||||
PyObject *MakeSingleParam(int index, PythonTypeDescriptor &td);
|
||||
PRBool GetIIDForINTERFACE_ID(int index, const nsIID **ppret);
|
||||
nsresult GetArrayType(PRUint8 index, PRUint8 *ret);
|
||||
PRUint32 GetSizeIs( int var_index, PRBool is_arg1);
|
||||
PRBool SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size);
|
||||
PRBool CanSetSizeIs( int var_index, PRBool is_arg1 );
|
||||
|
||||
|
||||
nsXPTCMiniVariant* m_params;
|
||||
const nsXPTMethodInfo *m_info;
|
||||
int m_method_index;
|
||||
PythonTypeDescriptor *m_python_type_desc_array;
|
||||
int m_num_type_descs;
|
||||
|
||||
};
|
||||
|
||||
// Misc converters.
|
||||
PyObject *PyObject_FromXPTTypeDescriptor( const XPTTypeDescriptor *d);
|
||||
PyObject *PyObject_FromXPTParamDescriptor( const XPTParamDescriptor *d);
|
||||
PyObject *PyObject_FromXPTMethodDescriptor( const XPTMethodDescriptor *d);
|
||||
PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *d);
|
||||
|
||||
|
||||
// DLL reference counting functions.
|
||||
// Although we maintain the count, we never actually
|
||||
// finalize Python when it hits zero!
|
||||
void PyXPCOM_DLLAddRef();
|
||||
void PyXPCOM_DLLRelease();
|
||||
|
||||
/*************************************************************************
|
||||
**************************************************************************
|
||||
|
||||
LOCKING AND THREADING
|
||||
|
||||
**************************************************************************
|
||||
*************************************************************************/
|
||||
|
||||
//
|
||||
// We have 2 discrete locks in use (when no free-threaded is used, anyway).
|
||||
// The first type of lock is the global Python lock. This is the standard lock
|
||||
// in use by Python, and must be used as documented by Python. Specifically, no
|
||||
// 2 threads may _ever_ call _any_ Python code (including INCREF/DECREF) without
|
||||
// first having this thread lock.
|
||||
//
|
||||
// The second type of lock is a "global framework lock", and used whenever 2 threads
|
||||
// of C code need access to global data. This is different than the Python
|
||||
// lock - this lock is used when no Python code can ever be called by the
|
||||
// threads, but the C code still needs thread-safety.
|
||||
|
||||
// We also supply helper classes which make the usage of these locks a one-liner.
|
||||
|
||||
// The "framework" lock, implemented as a PRLock
|
||||
PYXPCOM_EXPORT void PyXPCOM_AcquireGlobalLock(void);
|
||||
PYXPCOM_EXPORT void PyXPCOM_ReleaseGlobalLock(void);
|
||||
|
||||
// Helper class for the DLL global lock.
|
||||
//
|
||||
// This class magically waits for PyXPCOM framework global lock, and releases it
|
||||
// when finished.
|
||||
// NEVER new one of these objects - only use on the stack!
|
||||
class CEnterLeaveXPCOMFramework {
|
||||
public:
|
||||
CEnterLeaveXPCOMFramework() {PyXPCOM_AcquireGlobalLock();}
|
||||
~CEnterLeaveXPCOMFramework() {PyXPCOM_ReleaseGlobalLock();}
|
||||
};
|
||||
|
||||
// Python thread-lock stuff. Free-threading patches use different semantics, but
|
||||
// these are abstracted away here...
|
||||
//#include <threadstate.h>
|
||||
|
||||
// Helper class for Enter/Leave Python
|
||||
//
|
||||
// This class magically waits for the Python global lock, and releases it
|
||||
// when finished.
|
||||
|
||||
// Nested invocations will deadlock, so be careful.
|
||||
|
||||
// NEVER new one of these objects - only use on the stack!
|
||||
|
||||
extern PYXPCOM_EXPORT PyInterpreterState *PyXPCOM_InterpreterState;
|
||||
extern PYXPCOM_EXPORT PRBool PyXPCOM_ThreadState_Ensure();
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_ThreadState_Free();
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_ThreadState_Clear();
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_InterpreterLock_Acquire();
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_InterpreterLock_Release();
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_MakePendingCalls();
|
||||
|
||||
extern PYXPCOM_EXPORT PRBool PyXPCOM_Globals_Ensure();
|
||||
|
||||
class CEnterLeavePython {
|
||||
public:
|
||||
CEnterLeavePython() {
|
||||
created = PyXPCOM_ThreadState_Ensure();
|
||||
PyXPCOM_InterpreterLock_Acquire();
|
||||
if (created) {
|
||||
// If pending python calls are waiting as we enter Python,
|
||||
// it will generally mean an asynch signal handler, etc.
|
||||
// We can either call it here, or wait for Python to call it
|
||||
// as part of its "even 'n' opcodes" check. If we wait for
|
||||
// Python to check it and the pending call raises an exception,
|
||||
// then it is _our_ code that will fail - this is unfair,
|
||||
// as the signal was raised before we were entered - indeed,
|
||||
// we may be directly responding to the signal!
|
||||
// Thus, we flush all the pending calls here, and report any
|
||||
// exceptions via our normal exception reporting mechanism.
|
||||
// We can then execute our code in the knowledge that only
|
||||
// signals raised _while_ we are executing will cause exceptions.
|
||||
PyXPCOM_MakePendingCalls();
|
||||
}
|
||||
}
|
||||
~CEnterLeavePython() {
|
||||
// The interpreter state must be cleared
|
||||
// _before_ we release the lock, as some of
|
||||
// the sys. attributes cleared (eg, the current exception)
|
||||
// may need the lock to invoke their destructors -
|
||||
// specifically, when exc_value is a class instance, and
|
||||
// the exception holds the last reference!
|
||||
if ( created )
|
||||
PyXPCOM_ThreadState_Clear();
|
||||
PyXPCOM_InterpreterLock_Release();
|
||||
if ( created )
|
||||
PyXPCOM_ThreadState_Free();
|
||||
}
|
||||
private:
|
||||
PRBool created;
|
||||
};
|
||||
|
||||
#endif // __PYXPCOM_H__
|
||||
49
mozilla/extensions/python/xpcom/src/PyXPCOM_std.h
Normal file
49
mozilla/extensions/python/xpcom/src/PyXPCOM_std.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// standard include - sets up all the defines used by
|
||||
// the mozilla make process - too lazy to work out how to integrate
|
||||
// with their make, so this will do!
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
// Main Mozilla cross-platform declarations.
|
||||
#include "xp_core.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
# ifndef DEBUG
|
||||
# define DEBUG
|
||||
# endif
|
||||
|
||||
# define DEVELOPER_DEBUG
|
||||
# define NS_DEBUG
|
||||
# define DEBUG_markh
|
||||
#endif // DEBUG
|
||||
|
||||
#include <nsIAllocator.h>
|
||||
#include <nsIWeakReference.h>
|
||||
#include <nsXPIDLString.h>
|
||||
#include <nsCRT.h>
|
||||
#include <xptcall.h>
|
||||
#include <xpt_xdr.h>
|
||||
|
||||
// This header is considered internal - hence
|
||||
// we can use it to trigger "exports"
|
||||
#define BUILD_PYXPCOM
|
||||
|
||||
#ifdef HAVE_LONG_LONG
|
||||
// Mozilla also defines this - we undefine it to
|
||||
// prevent a compiler warning.
|
||||
# undef HAVE_LONG_LONG
|
||||
#endif // HAVE_LONG_LONG
|
||||
|
||||
#include "Python.h"
|
||||
#include "PyXPCOM.h"
|
||||
136
mozilla/extensions/python/xpcom/src/Pyxpt_info.cpp
Normal file
136
mozilla/extensions/python/xpcom/src/Pyxpt_info.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// Pyxpt_info.cpp - wrappers for the xpt_info objects.
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
#include "PyXPCOM_std.h"
|
||||
|
||||
PyObject *PyObject_FromXPTTypeDescriptor( const XPTTypeDescriptor *d)
|
||||
{
|
||||
if (d==nsnull) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
return Py_BuildValue("bbbh",
|
||||
d->prefix.flags,
|
||||
d->argnum,
|
||||
d->argnum2,
|
||||
d->type.iface // this is actually a union!
|
||||
);
|
||||
}
|
||||
|
||||
PyObject *PyObject_FromXPTParamDescriptor( const XPTParamDescriptor *d)
|
||||
{
|
||||
if (d==nsnull) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
PyObject *ob = PyObject_FromXPTTypeDescriptor(&d->type);
|
||||
PyObject *ret = Py_BuildValue("bO", d->flags, ob);
|
||||
Py_DECREF(ob);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject *PyObject_FromXPTMethodDescriptor( const XPTMethodDescriptor *d)
|
||||
{
|
||||
if (d==nsnull) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
PyObject *ob_params = PyTuple_New(d->num_args);
|
||||
if (ob_params==NULL)
|
||||
return NULL;
|
||||
for (int i=0;i<d->num_args;i++)
|
||||
PyTuple_SET_ITEM(ob_params, i, PyObject_FromXPTParamDescriptor(d->params+i));
|
||||
PyObject *ob_ret = PyObject_FromXPTParamDescriptor(d->result);
|
||||
PyObject *ret = Py_BuildValue("bsOO", d->flags, d->name, ob_params, ob_ret);
|
||||
Py_XDECREF(ob_ret);
|
||||
Py_XDECREF(ob_params);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *c)
|
||||
{
|
||||
if (c==nsnull) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
PyObject *ob_type = PyObject_FromXPTTypeDescriptor(&c->type);
|
||||
if (ob_type==NULL)
|
||||
return NULL;
|
||||
PyObject *v = NULL;
|
||||
switch (c->type.prefix.flags) {
|
||||
case TD_INT8:
|
||||
v = PyInt_FromLong( c->value.i8 );
|
||||
break;
|
||||
case TD_INT16:
|
||||
v = PyInt_FromLong( c->value.i16 );
|
||||
break;
|
||||
case TD_INT32:
|
||||
v = PyInt_FromLong( c->value.i32 );
|
||||
break;
|
||||
case TD_INT64:
|
||||
v = PyLong_FromLongLong(c->value.i64);
|
||||
break;
|
||||
case TD_UINT8:
|
||||
v = PyInt_FromLong( c->value.ui8 );
|
||||
break;
|
||||
case TD_UINT16:
|
||||
v = PyInt_FromLong( c->value.ui16 );
|
||||
break;
|
||||
case TD_UINT32:
|
||||
v = PyInt_FromLong( c->value.ui8 );
|
||||
break;
|
||||
case TD_UINT64:
|
||||
v = PyLong_FromUnsignedLongLong(c->value.ui64);
|
||||
break;
|
||||
case TD_FLOAT:
|
||||
v = PyFloat_FromDouble(c->value.flt);
|
||||
break;
|
||||
case TD_DOUBLE:
|
||||
v = PyFloat_FromDouble(c->value.dbl);
|
||||
break;
|
||||
case TD_BOOL:
|
||||
v = c->value.bul ? Py_True : Py_False;
|
||||
Py_INCREF(v);
|
||||
break;
|
||||
case TD_CHAR:
|
||||
v = PyString_FromStringAndSize(&c->value.ch, 1);
|
||||
break;
|
||||
case TD_WCHAR:
|
||||
v = PyUnicode_FromUnicode(&c->value.wch, 1);
|
||||
break;
|
||||
// TD_VOID = 13,
|
||||
case TD_PNSIID:
|
||||
v = Py_nsIID::PyObjectFromIID(*c->value.iid);
|
||||
break;
|
||||
// TD_PBSTR = 15,
|
||||
case TD_PSTRING:
|
||||
v = PyString_FromString(c->value.str);
|
||||
break;
|
||||
case TD_PWSTRING:
|
||||
v = PyUnicode_FromUnicode(c->value.wstr, nsCRT::strlen(c->value.wstr));
|
||||
break;
|
||||
// TD_INTERFACE_TYPE = 18,
|
||||
// TD_INTERFACE_IS_TYPE = 19,
|
||||
// TD_ARRAY = 20,
|
||||
// TD_PSTRING_SIZE_IS = 21,
|
||||
// TD_PWSTRING_SIZE_IS = 22
|
||||
default:
|
||||
v = PyString_FromString("Unknown type code!!");
|
||||
break;
|
||||
|
||||
}
|
||||
PyObject *ret = Py_BuildValue("sbO", c->name, ob_type, v);
|
||||
Py_DECREF(ob_type);
|
||||
Py_DECREF(v);
|
||||
return ret;
|
||||
}
|
||||
194
mozilla/extensions/python/xpcom/src/TypeObject.cpp
Normal file
194
mozilla/extensions/python/xpcom/src/TypeObject.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIInterfaceInfoManager.h>
|
||||
#include <nsISupportsPrimitives.h>
|
||||
|
||||
|
||||
static PyTypeObject PyInterfaceType_Type = {
|
||||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0, /* Number of items for varobject */
|
||||
"interface-type", /* Name of this type */
|
||||
sizeof(PyTypeObject), /* Basic object size */
|
||||
0, /* Item size for varobject */
|
||||
0, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
PyType_Type.tp_getattr, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
PyType_Type.tp_repr, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_xxx1*/
|
||||
0, /*tp_xxx2*/
|
||||
0, /*tp_xxx3*/
|
||||
0, /*tp_xxx4*/
|
||||
"Define the behavior of a PythonCOM Interface type.",
|
||||
};
|
||||
|
||||
/*static*/ PRBool
|
||||
PyXPCOM_TypeObject::IsType(PyTypeObject *t)
|
||||
{
|
||||
return t->ob_type == &PyInterfaceType_Type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The type methods
|
||||
//
|
||||
/*static*/PyObject *
|
||||
PyXPCOM_TypeObject::Py_getattr(PyObject *self, char *name)
|
||||
{
|
||||
if (strcmp(name, "IID")==0)
|
||||
return Py_nsIID::PyObjectFromIID( ((Py_nsISupports *)self)->m_iid );
|
||||
|
||||
PyXPCOM_TypeObject *this_type = (PyXPCOM_TypeObject *)self->ob_type;
|
||||
return Py_FindMethodInChain(&this_type->chain, self, name);
|
||||
}
|
||||
|
||||
/*static*/int
|
||||
PyXPCOM_TypeObject::Py_setattr(PyObject *op, char *name, PyObject *v)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "%s has read-only attributes", op->ob_type->tp_name );
|
||||
PyErr_SetString(PyExc_TypeError, buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// @pymethod int|Py_nsISupports|__cmp__|Implements XPCOM rules for object identity.
|
||||
/*static*/int
|
||||
PyXPCOM_TypeObject::Py_cmp(PyObject *self, PyObject *other)
|
||||
{
|
||||
// @comm NOTE: Copied from COM - have not confirmed these rules are true for XPCOM
|
||||
// @comm As per the XPCOM rules for object identity, both objects are queried for nsISupports, and these values compared.
|
||||
// The only meaningful test is for equality - the result of other comparisons is undefined
|
||||
// (ie, determined by the object's relative addresses in memory.
|
||||
nsISupports *pUnkOther;
|
||||
nsISupports *pUnkThis;
|
||||
if (!Py_nsISupports::InterfaceFromPyObject(self, NS_GET_IID(nsISupports), &pUnkThis, PR_FALSE))
|
||||
return -1;
|
||||
if (!Py_nsISupports::InterfaceFromPyObject(other, NS_GET_IID(nsISupports), &pUnkOther, PR_FALSE)) {
|
||||
pUnkThis->Release();
|
||||
return -1;
|
||||
}
|
||||
int rc = pUnkThis==pUnkOther ? 0 :
|
||||
(pUnkThis < pUnkOther ? -1 : 1);
|
||||
pUnkThis->Release();
|
||||
pUnkOther->Release();
|
||||
return rc;
|
||||
}
|
||||
|
||||
// @pymethod int|Py_nsISupports|__hash__|Implement a hash-code for the XPCOM object using XPCOM identity rules.
|
||||
/*static*/long PyXPCOM_TypeObject::Py_hash(PyObject *self)
|
||||
{
|
||||
// We always return the value of the nsISupports *.
|
||||
nsISupports *pUnkThis;
|
||||
if (!Py_nsISupports::InterfaceFromPyObject(self, NS_GET_IID(nsISupports), &pUnkThis, PR_FALSE))
|
||||
return -1;
|
||||
long ret = _Py_HashPointer(pUnkThis);
|
||||
pUnkThis->Release();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// @method string|Py_nsISupports|__repr__|Called to create a representation of a Py_nsISupports object
|
||||
/*static */PyObject *
|
||||
PyXPCOM_TypeObject::Py_repr(PyObject *self)
|
||||
{
|
||||
// @comm The repr of this object displays both the object's address, and its attached nsISupports's address
|
||||
Py_nsISupports *pis = (Py_nsISupports *)self;
|
||||
// Try and get the IID name.
|
||||
char *iid_repr;
|
||||
nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
|
||||
if (iim!=nsnull)
|
||||
iim->GetNameForIID(&pis->m_iid, &iid_repr);
|
||||
if (iid_repr==nsnull)
|
||||
// no IIM available, or it doesnt know the name.
|
||||
iid_repr = pis->m_iid.ToString();
|
||||
// XXX - need some sort of buffer overflow.
|
||||
char buf[512];
|
||||
sprintf(buf, "<XPCOM object (%s) at 0x%p/0x%p>", iid_repr, self, pis->m_obj);
|
||||
nsAllocator::Free(iid_repr);
|
||||
return PyString_FromString(buf);
|
||||
}
|
||||
|
||||
/*static */PyObject *
|
||||
PyXPCOM_TypeObject::Py_str(PyObject *self)
|
||||
{
|
||||
Py_nsISupports *pis = (Py_nsISupports *)self;
|
||||
nsresult rv;
|
||||
char *val = NULL;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
{ // scope to kill pointer while thread-lock released.
|
||||
nsCOMPtr<nsISupportsString> ss( do_QueryInterface(pis->m_obj, &rv ));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = ss->ToString(&val);
|
||||
} // end-scope
|
||||
Py_END_ALLOW_THREADS;
|
||||
PyObject *ret;
|
||||
if (NS_FAILED(rv))
|
||||
ret = Py_repr(self);
|
||||
else
|
||||
ret = PyString_FromString(val);
|
||||
if (val) nsAllocator::Free(val);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* static */void
|
||||
PyXPCOM_TypeObject::Py_dealloc(PyObject *self)
|
||||
{
|
||||
delete (Py_nsISupports *)self;
|
||||
}
|
||||
|
||||
PyXPCOM_TypeObject::PyXPCOM_TypeObject( const char *name, PyXPCOM_TypeObject *pBase, int typeSize, struct PyMethodDef* methodList, PyXPCOM_I_CTOR thector)
|
||||
{
|
||||
static const PyTypeObject type_template = {
|
||||
PyObject_HEAD_INIT(&PyInterfaceType_Type)
|
||||
0, /*ob_size*/
|
||||
"XPCOMTypeTemplate", /*tp_name*/
|
||||
sizeof(Py_nsISupports), /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
Py_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
Py_getattr, /* tp_getattr */
|
||||
Py_setattr, /* tp_setattr */
|
||||
Py_cmp, /* tp_compare */
|
||||
Py_repr, /* tp_repr */
|
||||
0, /* tp_as_number*/
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
Py_hash, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
Py_str, /* tp_str */
|
||||
};
|
||||
|
||||
*((PyTypeObject *)this) = type_template;
|
||||
|
||||
chain.methods = methodList;
|
||||
chain.link = pBase ? &pBase->chain : NULL;
|
||||
|
||||
baseType = pBase;
|
||||
ctor = thector;
|
||||
|
||||
// cast away const, as Python doesnt use it.
|
||||
tp_name = (char *)name;
|
||||
tp_basicsize = typeSize;
|
||||
}
|
||||
|
||||
PyXPCOM_TypeObject::~PyXPCOM_TypeObject()
|
||||
{
|
||||
}
|
||||
2092
mozilla/extensions/python/xpcom/src/VariantUtils.cpp
Normal file
2092
mozilla/extensions/python/xpcom/src/VariantUtils.cpp
Normal file
File diff suppressed because it is too large
Load Diff
217
mozilla/extensions/python/xpcom/src/dllmain.cpp
Normal file
217
mozilla/extensions/python/xpcom/src/dllmain.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <prthread.h>
|
||||
|
||||
#ifdef XP_WIN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
static PRInt32 g_cLockCount = 0;
|
||||
static PRBool bDidInitPython = PR_FALSE;
|
||||
static PyThreadState *ptsGlobal = nsnull;
|
||||
PyInterpreterState *PyXPCOM_InterpreterState;
|
||||
static PRLock *g_lockMain = nsnull;
|
||||
|
||||
PRUintn tlsIndex = 0;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Thread-state helpers/global functions.
|
||||
//
|
||||
|
||||
// This function must be called at some time when the interpreter lock and state is valid.
|
||||
// Called by init{module} functions and also COM factory entry point.
|
||||
void PyXPCOM_InterpreterState_Ensure()
|
||||
{
|
||||
if (PyXPCOM_InterpreterState==NULL) {
|
||||
PyThreadState *threadStateSave = PyThreadState_Swap(NULL);
|
||||
if (threadStateSave==NULL)
|
||||
Py_FatalError("Can not setup interpreter state, as current state is invalid");
|
||||
|
||||
PyXPCOM_InterpreterState = threadStateSave->interp;
|
||||
PyThreadState_Swap(threadStateSave);
|
||||
}
|
||||
}
|
||||
|
||||
void PyXPCOM_InterpreterState_Free()
|
||||
{
|
||||
PyXPCOM_ThreadState_Free();
|
||||
PyXPCOM_InterpreterState = NULL; // Eek - should I be freeing something?
|
||||
}
|
||||
|
||||
// This structure is stored in the TLS slot. At this stage only a Python thread state
|
||||
// is kept, but this may change in the future...
|
||||
struct ThreadData{
|
||||
PyThreadState *ts;
|
||||
};
|
||||
|
||||
// Ensure that we have a Python thread state available to use.
|
||||
// If this is called for the first time on a thread, it will allocate
|
||||
// the thread state. This does NOT change the state of the Python lock.
|
||||
// Returns TRUE if a new thread state was created, or FALSE if a
|
||||
// thread state already existed.
|
||||
PRBool PyXPCOM_ThreadState_Ensure()
|
||||
{
|
||||
ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
|
||||
if (pData==NULL) { /* First request on this thread */
|
||||
/* Check we have an interpreter state */
|
||||
if (PyXPCOM_InterpreterState==NULL) {
|
||||
Py_FatalError("Can not setup thread state, as have no interpreter state");
|
||||
}
|
||||
pData = (ThreadData *)nsAllocator::Alloc(sizeof(ThreadData));
|
||||
if (!pData)
|
||||
Py_FatalError("Out of memory allocating thread state.");
|
||||
memset(pData, 0, sizeof(*pData));
|
||||
if (NS_FAILED( PR_SetThreadPrivate( tlsIndex, pData ) ) ) {
|
||||
NS_ABORT_IF_FALSE(0, "Could not create thread data for this thread!");
|
||||
Py_FatalError("Could not thread private thread data!");
|
||||
}
|
||||
pData->ts = PyThreadState_New(PyXPCOM_InterpreterState);
|
||||
return PR_TRUE; // Did create a thread state state
|
||||
}
|
||||
return PR_FALSE; // Thread state was previously created
|
||||
}
|
||||
|
||||
// Asuming we have a valid thread state, acquire the Python lock.
|
||||
void PyXPCOM_InterpreterLock_Acquire()
|
||||
{
|
||||
ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
|
||||
NS_ABORT_IF_FALSE(pData, "Have no thread data for this thread!");
|
||||
PyThreadState *thisThreadState = pData->ts;
|
||||
PyEval_AcquireThread(thisThreadState);
|
||||
}
|
||||
|
||||
// Asuming we have a valid thread state, release the Python lock.
|
||||
void PyXPCOM_InterpreterLock_Release()
|
||||
{
|
||||
ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
|
||||
NS_ABORT_IF_FALSE(pData, "Have no thread data for this thread!");
|
||||
PyThreadState *thisThreadState = pData->ts;
|
||||
PyEval_ReleaseThread(thisThreadState);
|
||||
}
|
||||
|
||||
// Free the thread state for the current thread
|
||||
// (Presumably previously create with a call to
|
||||
// PyXPCOM_ThreadState_Ensure)
|
||||
void PyXPCOM_ThreadState_Free()
|
||||
{
|
||||
ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
|
||||
if (!pData) return;
|
||||
PyThreadState *thisThreadState = pData->ts;
|
||||
PyThreadState_Delete(thisThreadState);
|
||||
PR_SetThreadPrivate(tlsIndex, NULL);
|
||||
nsAllocator::Free(pData);
|
||||
}
|
||||
|
||||
void PyXPCOM_ThreadState_Clear()
|
||||
{
|
||||
ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
|
||||
PyThreadState *thisThreadState = pData->ts;
|
||||
PyThreadState_Clear(thisThreadState);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Lock/exclusion global functions.
|
||||
//
|
||||
|
||||
void PyXPCOM_AcquireGlobalLock(void)
|
||||
{
|
||||
NS_PRECONDITION(g_lockMain != nsnull, "Cant acquire a NULL lock!");
|
||||
PR_Lock(g_lockMain);
|
||||
}
|
||||
void PyXPCOM_ReleaseGlobalLock(void)
|
||||
{
|
||||
NS_PRECONDITION(g_lockMain != nsnull, "Cant release a NULL lock!");
|
||||
PR_Unlock(g_lockMain);
|
||||
}
|
||||
|
||||
void PyXPCOM_DLLAddRef(void)
|
||||
{
|
||||
// Must be thread-safe, although cant have the Python lock!
|
||||
CEnterLeaveXPCOMFramework _celf;
|
||||
PRInt32 cnt = PR_AtomicIncrement(&g_cLockCount);
|
||||
if (cnt==1) { // First call
|
||||
if (!Py_IsInitialized()) {
|
||||
Py_Initialize();
|
||||
// Make sure our Windows framework is all setup.
|
||||
PyXPCOM_Globals_Ensure();
|
||||
// Make sure we have _something_ as sys.argv.
|
||||
if (PySys_GetObject("argv")==NULL) {
|
||||
PyObject *path = PyList_New(0);
|
||||
PyObject *str = PyString_FromString("");
|
||||
PyList_Append(path, str);
|
||||
PySys_SetObject("argv", path);
|
||||
Py_XDECREF(path);
|
||||
Py_XDECREF(str);
|
||||
}
|
||||
|
||||
// Must force Python to start using thread locks, as
|
||||
// we are free-threaded (maybe, I think, sometimes :-)
|
||||
PyEval_InitThreads();
|
||||
// Release Python lock, as first thing we do is re-get it.
|
||||
ptsGlobal = PyEval_SaveThread();
|
||||
// NOTE: We never finalize Python!!
|
||||
}
|
||||
}
|
||||
}
|
||||
void PyXPCOM_DLLRelease(void)
|
||||
{
|
||||
PR_AtomicDecrement(&g_cLockCount);
|
||||
}
|
||||
|
||||
extern "C" PRBool _init(void)
|
||||
{
|
||||
PRStatus status;
|
||||
g_lockMain = PR_NewLock();
|
||||
status = PR_NewThreadPrivateIndex( &tlsIndex, NULL );
|
||||
NS_WARN_IF_FALSE(status==0, "Could not allocate TLS storage");
|
||||
if (NS_FAILED(status)) {
|
||||
PR_DestroyLock(g_lockMain);
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
extern "C" void _fini(void)
|
||||
{
|
||||
PR_DestroyLock(g_lockMain);
|
||||
// I can't locate a way to kill this -
|
||||
// should I pass a dtor to PR_NewThreadPrivateIndex??
|
||||
// TlsFree(tlsIndex);
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
||||
extern "C" __declspec(dllexport)
|
||||
BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved)
|
||||
{
|
||||
switch (dwReason) {
|
||||
case DLL_PROCESS_ATTACH: {
|
||||
if (!_init())
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
case DLL_PROCESS_DETACH:
|
||||
{
|
||||
_fini();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return TRUE; // ok
|
||||
}
|
||||
#endif // XP_WIN
|
||||
392
mozilla/extensions/python/xpcom/src/loader/pyloader.cpp
Normal file
392
mozilla/extensions/python/xpcom/src/loader/pyloader.cpp
Normal file
@@ -0,0 +1,392 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// pyloader
|
||||
//
|
||||
// Not part of the main Python _xpcom package, but a seperate, thin DLL.
|
||||
//
|
||||
// The main loader and registrar for Python. A thin DLL that is designed to live in
|
||||
// the xpcom "components" directory. Simply locates and loads the standard
|
||||
// _xpcom support module and transfers control to that.
|
||||
|
||||
#include "xp_core.h"
|
||||
#include "nsIComponentLoader.h"
|
||||
#include "nsIRegistry.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIModule.h"
|
||||
|
||||
#include <nsFileStream.h> // For console logging.
|
||||
|
||||
#ifdef HAVE_LONG_LONG
|
||||
#undef HAVE_LONG_LONG
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Can only assume dynamic loading on Windows.
|
||||
#define LOADER_LINKS_WITH_PYTHON
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LOADER_LINKS_WITH_PYTHON
|
||||
#include "Python.h"
|
||||
|
||||
static PyThreadState *ptsGlobal = nsnull;
|
||||
static char *PyTraceback_AsString(PyObject *exc_tb);
|
||||
|
||||
#else // LOADER_LINKS_WITH_PYTHON
|
||||
|
||||
static PRBool find_xpcom_module(char *buf, size_t bufsize);
|
||||
|
||||
#endif // LOADER_LINKS_WITH_PYTHON
|
||||
|
||||
|
||||
#ifdef XP_WIN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_UNIX
|
||||
#include <dlfcn.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef nsresult (*pfnPyXPCOM_NSGetModule)(nsIComponentManager *servMgr,
|
||||
nsIFile* location,
|
||||
nsIModule** result);
|
||||
|
||||
|
||||
pfnPyXPCOM_NSGetModule pfnEntryPoint = nsnull;
|
||||
|
||||
|
||||
static void LogError(const char *fmt, ...);
|
||||
|
||||
extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
|
||||
nsIFile* location,
|
||||
nsIModule** result)
|
||||
{
|
||||
// What to do for other platforms here?
|
||||
// I tried using their nsDll class, but it wont allow
|
||||
// a LoadLibrary() - it insists on a full path it can load.
|
||||
// So if Im going to the trouble of locating the DLL on Windows,
|
||||
// I may as well just do the whole thing myself.
|
||||
#ifdef LOADER_LINKS_WITH_PYTHON
|
||||
PRBool bDidInitPython = !Py_IsInitialized(); // well, I will next line, anyway :-)
|
||||
if (bDidInitPython) {
|
||||
// If Python was already initialized, we almost certainly
|
||||
// do not have the thread-lock, so can not attempt to import anything
|
||||
// We simply must assume/hope that Python already has our module loaded.
|
||||
Py_Initialize();
|
||||
if (!Py_IsInitialized()) {
|
||||
LogError("Python initialization failed!\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PyObject *mod = PyImport_ImportModule("xpcom._xpcom");
|
||||
if (mod==NULL) {
|
||||
LogError("Could not import the Python XPCOM extension\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
#endif // LOADER_LINKS_WITH_PYTHON
|
||||
if (pfnEntryPoint == nsnull) {
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
||||
#ifdef DEBUG
|
||||
const char *mod_name = "_xpcom_d.pyd";
|
||||
#else
|
||||
const char *mod_name = "_xpcom.pyd";
|
||||
#endif
|
||||
HMODULE hmod = GetModuleHandle(mod_name);
|
||||
if (hmod==NULL) {
|
||||
LogError("Could not get a handle to the Python XPCOM extension\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
pfnEntryPoint = (pfnPyXPCOM_NSGetModule)GetProcAddress(hmod, "PyXPCOM_NSGetModule");
|
||||
#endif // XP_WIN
|
||||
|
||||
#ifdef XP_UNIX
|
||||
static char module_path[1024];
|
||||
if (!find_xpcom_module(module_path, sizeof(module_path)))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
void *handle = dlopen(module_path, RTLD_GLOBAL | RTLD_LAZY);
|
||||
if (handle==NULL) {
|
||||
LogError("Could not open the Python XPCOM extension at '%s' - '%s'\n", module_path, dlerror());
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
pfnEntryPoint = (pfnPyXPCOM_NSGetModule)dlsym(handle, "PyXPCOM_NSGetModule");
|
||||
#endif // XP_UNIX
|
||||
}
|
||||
if (pfnEntryPoint==NULL) {
|
||||
LogError("Could not load main Python entry point\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef LOADER_LINKS_WITH_PYTHON
|
||||
// We abandon the thread-lock, as the first thing Python does
|
||||
// is re-establish the lock (the Python thread-state story SUCKS!!!
|
||||
|
||||
if (bDidInitPython)
|
||||
ptsGlobal = PyEval_SaveThread();
|
||||
// Note this is never restored, and Python is never finalized!
|
||||
#endif // LOADER_LINKS_WITH_PYTHON
|
||||
return (*pfnEntryPoint)(servMgr, location, result);
|
||||
}
|
||||
|
||||
// The internal helper that actually moves the
|
||||
// formatted string to the target!
|
||||
|
||||
void LogMessage(const char *prefix, const char *pszMessageText)
|
||||
{
|
||||
nsOutputConsoleStream console;
|
||||
console << prefix << pszMessageText;
|
||||
}
|
||||
|
||||
// A helper for the various logging routines.
|
||||
static void VLogF(const char *prefix, const char *fmt, va_list argptr)
|
||||
{
|
||||
char buff[512];
|
||||
|
||||
vsprintf(buff, fmt, argptr);
|
||||
|
||||
LogMessage(prefix, buff);
|
||||
}
|
||||
|
||||
static void LogError(const char *fmt, ...)
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker, fmt);
|
||||
VLogF("PyXPCOM Loader Error: ", fmt, marker);
|
||||
#ifdef LOADER_LINKS_WITH_PYTHON
|
||||
// If we have a Python exception, also log that:
|
||||
PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
|
||||
PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
|
||||
if (exc_typ) {
|
||||
char *string1 = nsnull;
|
||||
nsOutputStringStream streamout(string1);
|
||||
|
||||
if (exc_tb) {
|
||||
const char *szTraceback = PyTraceback_AsString(exc_tb);
|
||||
if (szTraceback == NULL)
|
||||
streamout << "Can't get the traceback info!";
|
||||
else {
|
||||
streamout << "Traceback (most recent call last):\n";
|
||||
streamout << szTraceback;
|
||||
PyMem_Free((ANY *)szTraceback);
|
||||
}
|
||||
}
|
||||
PyObject *temp = PyObject_Str(exc_typ);
|
||||
if (temp) {
|
||||
streamout << PyString_AsString(temp);
|
||||
Py_DECREF(temp);
|
||||
} else
|
||||
streamout << "Can convert exception to a string!";
|
||||
streamout << ": ";
|
||||
if (exc_val != NULL) {
|
||||
temp = PyObject_Str(exc_val);
|
||||
if (temp) {
|
||||
streamout << PyString_AsString(temp);
|
||||
Py_DECREF(temp);
|
||||
} else
|
||||
streamout << "Can convert exception value to a string!";
|
||||
}
|
||||
streamout << "\n";
|
||||
LogMessage("PyXPCOM Exception:", string1);
|
||||
}
|
||||
PyErr_Restore(exc_typ, exc_val, exc_tb);
|
||||
#endif // LOADER_LINKS_WITH_PYTHON
|
||||
}
|
||||
|
||||
static void LogWarning(const char *fmt, ...)
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker, fmt);
|
||||
VLogF("PyXPCOM Loader Warning: ", fmt, marker);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void LogDebug(const char *fmt, ...)
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker, fmt);
|
||||
VLogF("PyXPCOM Loader Debug: ", fmt, marker);
|
||||
}
|
||||
#else
|
||||
#define LogDebug()
|
||||
#endif
|
||||
|
||||
#ifdef LOADER_LINKS_WITH_PYTHON
|
||||
|
||||
/* Obtains a string from a Python traceback.
|
||||
This is the exact same string as "traceback.print_exc" would return.
|
||||
|
||||
Pass in a Python traceback object (probably obtained from PyErr_Fetch())
|
||||
Result is a string which must be free'd using PyMem_Free()
|
||||
*/
|
||||
#define TRACEBACK_FETCH_ERROR(what) {errMsg = what; goto done;}
|
||||
|
||||
char *PyTraceback_AsString(PyObject *exc_tb)
|
||||
{
|
||||
char *errMsg = NULL; /* a static that hold a local error message */
|
||||
char *result = NULL; /* a valid, allocated result. */
|
||||
PyObject *modStringIO = NULL;
|
||||
PyObject *modTB = NULL;
|
||||
PyObject *obFuncStringIO = NULL;
|
||||
PyObject *obStringIO = NULL;
|
||||
PyObject *obFuncTB = NULL;
|
||||
PyObject *argsTB = NULL;
|
||||
PyObject *obResult = NULL;
|
||||
|
||||
/* Import the modules we need - cStringIO and traceback */
|
||||
modStringIO = PyImport_ImportModule("cStringIO");
|
||||
if (modStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant import cStringIO\n");
|
||||
|
||||
modTB = PyImport_ImportModule("traceback");
|
||||
if (modTB==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant import traceback\n");
|
||||
/* Construct a cStringIO object */
|
||||
obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO");
|
||||
if (obFuncStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant find cStringIO.StringIO\n");
|
||||
obStringIO = PyObject_CallObject(obFuncStringIO, NULL);
|
||||
if (obStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cStringIO.StringIO() failed\n");
|
||||
/* Get the traceback.print_exception function, and call it. */
|
||||
obFuncTB = PyObject_GetAttrString(modTB, "print_tb");
|
||||
if (obFuncTB==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant find traceback.print_tb\n");
|
||||
|
||||
argsTB = Py_BuildValue("OOO",
|
||||
exc_tb ? exc_tb : Py_None,
|
||||
Py_None,
|
||||
obStringIO);
|
||||
if (argsTB==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant make print_tb arguments\n");
|
||||
|
||||
obResult = PyObject_CallObject(obFuncTB, argsTB);
|
||||
if (obResult==NULL)
|
||||
TRACEBACK_FETCH_ERROR("traceback.print_tb() failed\n");
|
||||
/* Now call the getvalue() method in the StringIO instance */
|
||||
Py_DECREF(obFuncStringIO);
|
||||
obFuncStringIO = PyObject_GetAttrString(obStringIO, "getvalue");
|
||||
if (obFuncStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant find getvalue function\n");
|
||||
Py_DECREF(obResult);
|
||||
obResult = PyObject_CallObject(obFuncStringIO, NULL);
|
||||
if (obResult==NULL)
|
||||
TRACEBACK_FETCH_ERROR("getvalue() failed.\n");
|
||||
|
||||
/* And it should be a string all ready to go - duplicate it. */
|
||||
if (!PyString_Check(obResult))
|
||||
TRACEBACK_FETCH_ERROR("getvalue() did not return a string\n");
|
||||
|
||||
{ // a temp scope so I can use temp locals.
|
||||
char *tempResult = PyString_AsString(obResult);
|
||||
result = (char *)PyMem_Malloc(strlen(tempResult)+1);
|
||||
if (result==NULL)
|
||||
TRACEBACK_FETCH_ERROR("memory error duplicating the traceback string");
|
||||
|
||||
strcpy(result, tempResult);
|
||||
} // end of temp scope.
|
||||
done:
|
||||
/* All finished - first see if we encountered an error */
|
||||
if (result==NULL && errMsg != NULL) {
|
||||
result = (char *)PyMem_Malloc(strlen(errMsg)+1);
|
||||
if (result != NULL)
|
||||
/* if it does, not much we can do! */
|
||||
strcpy(result, errMsg);
|
||||
}
|
||||
Py_XDECREF(modStringIO);
|
||||
Py_XDECREF(modTB);
|
||||
Py_XDECREF(obFuncStringIO);
|
||||
Py_XDECREF(obStringIO);
|
||||
Py_XDECREF(obFuncTB);
|
||||
Py_XDECREF(argsTB);
|
||||
Py_XDECREF(obResult);
|
||||
return result;
|
||||
}
|
||||
|
||||
#else // LOADER_LINKS_WITH_PYTHON
|
||||
|
||||
#ifdef XP_UNIX
|
||||
|
||||
// From Python getpath.c
|
||||
#ifndef S_ISREG
|
||||
#define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
static int
|
||||
isfile(char *filename) /* Is file, not directory */
|
||||
{
|
||||
struct stat buf;
|
||||
if (stat(filename, &buf) != 0)
|
||||
return 0;
|
||||
if (!S_ISREG(buf.st_mode))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
isxfile(char *filename) /* Is executable file */
|
||||
{
|
||||
struct stat buf;
|
||||
if (stat(filename, &buf) != 0)
|
||||
return 0;
|
||||
if (!S_ISREG(buf.st_mode))
|
||||
return 0;
|
||||
if ((buf.st_mode & 0111) == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
isdir(char *filename) /* Is directory */
|
||||
{
|
||||
struct stat buf;
|
||||
if (stat(filename, &buf) != 0)
|
||||
return 0;
|
||||
if (!S_ISDIR(buf.st_mode))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
PRBool find_xpcom_module(char *buf, size_t bufsize)
|
||||
{
|
||||
char *pypath = getenv("PYTHONPATH");
|
||||
char *searchPath = pypath ? strdup(pypath) : NULL;
|
||||
char *tok = searchPath ? strtok(searchPath, ":") : NULL;
|
||||
while (tok != NULL) {
|
||||
int thissize = bufsize;
|
||||
int baselen = strlen(tok);
|
||||
strncpy(buf, tok, thissize);
|
||||
thissize-=baselen;
|
||||
if (thissize > 1 && buf[baselen-1] != '/') {
|
||||
buf[baselen++]='/';
|
||||
}
|
||||
strncpy(buf+baselen, "xpcom/_xpcommodule.so", thissize);
|
||||
// LogDebug("Python _xpcom module at '%s'?\n", buf);
|
||||
if (isfile(buf)) {
|
||||
// LogDebug("Found python _xpcom module at '%s'\n", buf);
|
||||
return PR_TRUE;
|
||||
}
|
||||
tok = strtok(NULL, ":");
|
||||
}
|
||||
LogError("Failed to find a Python _xpcom module\n");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
#endif // XP_UNIX
|
||||
|
||||
#endif // LOADER_LINKS_WITH_PYTHON
|
||||
|
||||
66
mozilla/extensions/python/xpcom/src/readme.html
Normal file
66
mozilla/extensions/python/xpcom/src/readme.html
Normal file
@@ -0,0 +1,66 @@
|
||||
<!-- Copyright (c) 2000-2001 ActiveState Tool Corporation. -->
|
||||
<!-- See the file LICENSE.txt for licensing information. -->
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Building the Python XPCOM package</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Building the Python XPCOM package.</h1>
|
||||
|
||||
<p>This file describes how to build the Python XPCOM C++ sources.</p>
|
||||
<p>There are the following steps</p>
|
||||
<ul>
|
||||
<li><a href="#ConfiguringTheEnvironment">Configure environment variables</a></li>
|
||||
<li><a href="#BuildingTheSources">Building the sources</a></li>
|
||||
</ul>
|
||||
<p>Testing etc is described in the <a href="../readme.html">main readme</a>.</p>
|
||||
<h2><a name="ConfiguringTheEnvironment">Configuring environment variables</a></h2>
|
||||
<h3> MOZ_SRC </h3>
|
||||
<p><b>Windows: </b>Run the standard MOZENV.BAT used to build Mozilla. This
|
||||
sets MOZ_SRC</p>
|
||||
<p><b>Unix:</b> Set MOZ_SRC to point to the base source directory - assumes
|
||||
"mozilla" sub-directory with mozilla directory tree under that. eg: assuming
|
||||
<i>/home/user/src/mozilla/dist/...</i>"</p>
|
||||
<pre>export MOZ_SRC=/home/user/src</pre>
|
||||
<h3>PYTHON_SRC</h3>
|
||||
<p><b>Windows:</b> Set <i> PYTHON_SRC</i> to point to the base Python source directory.
|
||||
eg: assuming <i>c:\src\python\PCBuild\...</i><pre>set PYTHON_SRC=c:\src\python</pre>
|
||||
<p>Unix: Set PYTHON_SRC to point to the base of an "installed" Python
|
||||
tree. eg:<pre>export PYTHON_SRC=/usr/local/ActivePython-1.6</pre>
|
||||
<h2><a name="BuildingTheSources">Building the sources</a></h2>
|
||||
<p>You must ensure some environment variables are setup. The section on <a href="#ConfiguringTheEnvironment">configuring
|
||||
environment variables explains how.</a></p>
|
||||
<p>There are 2 build processes to run All C++ sources are in the <i>xpcom\src</i>
|
||||
directory.:</p>
|
||||
<h3>Windows</h3>
|
||||
<ul>
|
||||
<li> Execute "compile.py" in this directory. This will take <i>Setup.in</i>, create an MSDev project, and build
|
||||
<i>..\_xpcom.pyd</i> and <i>..\_xpcom_d.pyd</i>"</li>
|
||||
<li> Change to the <i>loader</i> directory.</li>
|
||||
<li> Run <i>nmake -f makefile.win</i>. This will create <i>pyloader.dll</i>, and
|
||||
automatically copy it to the Mozilla build directory.</li>
|
||||
<a href="#ConfiguringTheEnvironment">
|
||||
</ul>
|
||||
<p>Finally, </a><a href="../readme.html#RunningTheTests">run the tests</a>,
|
||||
where we also test everything imports correctly.</p>
|
||||
<h3>Linux</h3>
|
||||
<p><b> NOTE:</b> Do not attempt to use "Setup.in" to create a Makefile </p>
|
||||
<ul>
|
||||
<li>Run "make" in this directory. This will create <i>../_xpcommodule.so</i></li>
|
||||
<li> Run "make" in the loader directory. This will create <i>libpyloader.so</i>,
|
||||
and copy it to the Mozilla directory.</li>
|
||||
<a href="#ConfiguringTheEnvironment">
|
||||
</ul>
|
||||
<p>Finally, </a><a href="../readme.html#RunningTheTests">running the tests</a>,
|
||||
where we also test everything imports correctly.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
532
mozilla/extensions/python/xpcom/src/xpcom.cpp
Normal file
532
mozilla/extensions/python/xpcom/src/xpcom.cpp
Normal file
@@ -0,0 +1,532 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIInterfaceInfoManager.h>
|
||||
#include <nsIFileSpec.h>
|
||||
#include <nsSpecialSystemDirectory.h>
|
||||
#include <nsIThread.h>
|
||||
#include <nsISupportsPrimitives.h>
|
||||
#include <nsIModule.h>
|
||||
#include <nsIInputStream.h>
|
||||
|
||||
#ifdef XP_WIN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
#include <nsIEventQueue.h>
|
||||
#include <nsIProxyObjectManager.h>
|
||||
|
||||
PYXPCOM_EXPORT PyObject *PyXPCOM_Error = NULL;
|
||||
extern void PyXPCOM_InterpreterState_Ensure();
|
||||
extern PRInt32 _PyXPCOM_GetGatewayCount(void);
|
||||
extern PRInt32 _PyXPCOM_GetInterfaceCount(void);
|
||||
|
||||
extern void AddDefaultGateway(PyObject *instance, nsISupports *gateway);
|
||||
|
||||
// Hrm - So we can't have templates, eh??
|
||||
// preprocessor to the rescue, I guess.
|
||||
#define PyXPCOM_INTERFACE_DEFINE(ClassName, InterfaceName, Methods ) \
|
||||
\
|
||||
extern struct PyMethodDef Methods[]; \
|
||||
\
|
||||
class ClassName : public Py_nsISupports \
|
||||
{ \
|
||||
public: \
|
||||
static PyXPCOM_TypeObject *type; \
|
||||
static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid) { \
|
||||
return new ClassName(pInitObj, iid); \
|
||||
} \
|
||||
static void InitType(PyObject *iidNameDict) { \
|
||||
type = new PyXPCOM_TypeObject( \
|
||||
#InterfaceName, \
|
||||
Py_nsISupports::type, \
|
||||
sizeof(ClassName), \
|
||||
Methods, \
|
||||
Constructor); \
|
||||
const nsIID &iid = NS_GET_IID(InterfaceName); \
|
||||
RegisterInterface(iid, type); \
|
||||
PyObject *iid_ob = Py_nsIID::PyObjectFromIID(iid); \
|
||||
PyDict_SetItemString(iidNameDict, "IID_"#InterfaceName, iid_ob); \
|
||||
Py_DECREF(iid_ob); \
|
||||
} \
|
||||
protected: \
|
||||
ClassName(nsISupports *p, const nsIID &iid) : \
|
||||
Py_nsISupports(p, iid, type) { \
|
||||
/* The IID _must_ be the IID of the interface we are wrapping! */ \
|
||||
NS_ABORT_IF_FALSE(iid.Equals(NS_GET_IID(InterfaceName)), "Bad IID"); \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
PyXPCOM_TypeObject *ClassName::type = NULL; \
|
||||
\
|
||||
// End of PyXPCOM_INTERFACE_DEFINE macro
|
||||
|
||||
// And the classes
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIComponentManager, nsIComponentManager, PyMethods_IComponentManager)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIInterfaceInfoManager, nsIInterfaceInfoManager, PyMethods_IInterfaceInfoManager)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIEnumerator, nsIEnumerator, PyMethods_IEnumerator)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsISimpleEnumerator, nsISimpleEnumerator, PyMethods_ISimpleEnumerator)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIInterfaceInfo, nsIInterfaceInfo, PyMethods_IInterfaceInfo)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIServiceManager, nsIServiceManager, PyMethods_IServiceManager)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIInputStream, nsIInputStream, PyMethods_IInputStream)
|
||||
|
||||
// "boot-strap" methods - interfaces we need to get the base
|
||||
// interface support!
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_NS_LocateSpecialSystemDirectory(PyObject *self, PyObject *args)
|
||||
{
|
||||
int typ;
|
||||
if (!PyArg_ParseTuple(args, "i", &typ))
|
||||
return NULL;
|
||||
nsIFileSpec *spec = NULL;
|
||||
nsSpecialSystemDirectory systemDir((nsSpecialSystemDirectory::SystemDirectories)typ);
|
||||
return PyString_FromString(systemDir.GetNativePathCString());
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_NS_NewFileSpec(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *szspec = NULL;
|
||||
if (!PyArg_ParseTuple(args, "|s", &szspec))
|
||||
return NULL;
|
||||
nsIFileSpec *spec = NULL;
|
||||
nsresult nr;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
nr = NS_NewFileSpec(&spec);
|
||||
if (NS_SUCCEEDED(nr) && spec && szspec)
|
||||
nr = spec->SetNativePath(szspec);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if (NS_FAILED(nr) || spec==nsnull)
|
||||
return PyXPCOM_BuildPyException(nr);
|
||||
return Py_nsISupports::PyObjectFromInterface(spec, NS_GET_IID(nsIFileSpec), PR_TRUE);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_NS_GetGlobalComponentManager(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
nsIComponentManager* cm;
|
||||
nsresult rv;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
rv = NS_GetGlobalComponentManager(&cm);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(rv) )
|
||||
return PyXPCOM_BuildPyException(rv);
|
||||
// NOTE - NS_GetGlobalComponentManager DOES NOT ADD A REFCOUNT
|
||||
// (naughty, naughty) - we we explicitly ask our converter to
|
||||
// add one, even tho this is not the common pattern.
|
||||
|
||||
// Return a type based on the IID
|
||||
// Can not auto-wrap the interface info manager as it is critical to
|
||||
// building the support we need for autowrap.
|
||||
return Py_nsISupports::PyObjectFromInterface(cm, NS_GET_IID(nsIComponentManager), PR_TRUE, PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_GetGlobalServiceManager(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
nsIServiceManager* sm;
|
||||
nsresult rv;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
rv = nsServiceManager::GetGlobalServiceManager(&sm);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(rv) )
|
||||
return PyXPCOM_BuildPyException(rv);
|
||||
// NOTE - GetGlobalServiceManager DOES NOT ADD A REFCOUNT
|
||||
// (naughty, naughty) - we we explicitly ask our converter to
|
||||
// add one, even tho this is not the common pattern.
|
||||
|
||||
// Return a type based on the IID
|
||||
// Can not auto-wrap the interface info manager as it is critical to
|
||||
// building the support we need for autowrap.
|
||||
return Py_nsISupports::PyObjectFromInterface(sm, NS_GET_IID(nsIServiceManager), PR_TRUE, PR_FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_XPTI_GetInterfaceInfoManager(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
nsIInterfaceInfoManager* im;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
im = XPTI_GetInterfaceInfoManager();
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( im == nsnull )
|
||||
return PyXPCOM_BuildPyException(NS_ERROR_FAILURE);
|
||||
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
// Can not auto-wrap the interface info manager as it is critical to
|
||||
// building the support we need for autowrap.
|
||||
return Py_nsISupports::PyObjectFromInterface(im, NS_GET_IID(nsIInterfaceInfoManager), PR_FALSE, PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_XPTC_InvokeByIndex(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIS, *obParams;
|
||||
nsCOMPtr<nsISupports> pis;
|
||||
int index;
|
||||
|
||||
// We no longer rely on PyErr_Occurred() for our error state,
|
||||
// but keeping this assertion can't hurt - it should still always be true!
|
||||
NS_WARN_IF_FALSE(!PyErr_Occurred(), "Should be no pending Python error!");
|
||||
|
||||
if (!PyArg_ParseTuple(args, "OiO", &obIS, &index, &obParams))
|
||||
return NULL;
|
||||
|
||||
// Ack! We must ask for the "native" interface supported by
|
||||
// the object, not specifically nsISupports, else we may not
|
||||
// back the same pointer (eg, Python, following identity rules,
|
||||
// will return the "original" gateway when QI'd for nsISupports)
|
||||
if (!Py_nsISupports::InterfaceFromPyObject(
|
||||
obIS,
|
||||
Py_nsIID_NULL,
|
||||
getter_AddRefs(pis),
|
||||
PR_FALSE))
|
||||
return NULL;
|
||||
|
||||
PyXPCOM_InterfaceVariantHelper arg_helper;
|
||||
if (!arg_helper.Init(obParams))
|
||||
return NULL;
|
||||
|
||||
if (!arg_helper.FillArray())
|
||||
return NULL;
|
||||
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = XPTC_InvokeByIndex(pis, index, arg_helper.m_num_array, arg_helper.m_var_array);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
return arg_helper.MakePythonResult();
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_WrapObject(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *ob, *obIID;
|
||||
if (!PyArg_ParseTuple(args, "OO", &ob, &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
|
||||
nsISupports *ret = NULL;
|
||||
nsresult r = PyXPCOM_XPTStub::CreateNew(ob, iid, (void **)&ret);
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
// _ALL_ wrapped objects are associated with a weak-ref
|
||||
// to their "main" instance.
|
||||
AddDefaultGateway(ob, ret); // inject a weak reference to myself into the instance.
|
||||
|
||||
// Now wrap it in an interface.
|
||||
return Py_nsISupports::PyObjectFromInterface(ret, iid, PR_FALSE);
|
||||
}
|
||||
|
||||
// @pymethod int|pythoncom|_GetInterfaceCount|Retrieves the number of interface objects currently in existance
|
||||
static PyObject *
|
||||
PyXPCOMMethod_GetInterfaceCount(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":_GetInterfaceCount"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(_PyXPCOM_GetInterfaceCount());
|
||||
// @comm If is occasionally a good idea to call this function before your Python program
|
||||
// terminates. If this function returns non-zero, then you still have PythonCOM objects
|
||||
// alive in your program (possibly in global variables).
|
||||
}
|
||||
|
||||
// @pymethod int|pythoncom|_GetGatewayCount|Retrieves the number of gateway objects currently in existance
|
||||
static PyObject *
|
||||
PyXPCOMMethod_GetGatewayCount(PyObject *self, PyObject *args)
|
||||
{
|
||||
// @comm This is the number of Python object that implement COM servers which
|
||||
// are still alive (ie, serving a client). The only way to reduce this count
|
||||
// is to have the process which uses these PythonCOM servers release its references.
|
||||
if (!PyArg_ParseTuple(args, ":_GetGatewayCount"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(_PyXPCOM_GetGatewayCount());
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_NS_ShutdownXPCOM(PyObject *self, PyObject *args)
|
||||
{
|
||||
// @comm This is the number of Python object that implement COM servers which
|
||||
// are still alive (ie, serving a client). The only way to reduce this count
|
||||
// is to have the process which uses these PythonCOM servers release its references.
|
||||
if (!PyArg_ParseTuple(args, ":NS_ShutdownXPCOM"))
|
||||
return NULL;
|
||||
nsresult nr;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
nr = NS_ShutdownXPCOM(nsnull);
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
// Dont raise an exception - as we are probably shutting down
|
||||
// and dont really case - just return the status
|
||||
return PyInt_FromLong(nr);
|
||||
}
|
||||
|
||||
static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
|
||||
|
||||
// A hack to work around their magic constants!
|
||||
static PyObject *
|
||||
PyXPCOMMethod_GetProxyForObject(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obQueue, *obIID, *obOb;
|
||||
int flags;
|
||||
if (!PyArg_ParseTuple(args, "OOOi", &obQueue, &obIID, &obOb, &flags))
|
||||
return NULL;
|
||||
nsIID iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
nsCOMPtr<nsISupports> pob;
|
||||
if (!Py_nsISupports::InterfaceFromPyObject(obOb, iid, getter_AddRefs(pob), PR_FALSE))
|
||||
return NULL;
|
||||
nsIEventQueue *pQueue = NULL;
|
||||
nsIEventQueue *pQueueRelease = NULL;
|
||||
|
||||
if (PyInt_Check(obQueue)) {
|
||||
pQueue = (nsIEventQueue *)PyInt_AsLong(obQueue);
|
||||
} else {
|
||||
if (!Py_nsISupports::InterfaceFromPyObject(obQueue, NS_GET_IID(nsIEventQueue), (nsISupports **)&pQueue, PR_TRUE))
|
||||
return NULL;
|
||||
pQueueRelease = pQueue;
|
||||
}
|
||||
|
||||
nsresult rv_proxy;
|
||||
nsISupports *presult = nsnull;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
NS_WITH_SERVICE(nsIProxyObjectManager,
|
||||
proxyMgr,
|
||||
kProxyObjectManagerCID,
|
||||
&rv_proxy);
|
||||
|
||||
if ( NS_SUCCEEDED(rv_proxy) ) {
|
||||
rv_proxy = proxyMgr->GetProxyForObject(pQueue,
|
||||
iid,
|
||||
pob,
|
||||
flags,
|
||||
(void **)&presult);
|
||||
}
|
||||
if (pQueueRelease)
|
||||
pQueueRelease->Release();
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
PyObject *result;
|
||||
if (NS_SUCCEEDED(rv_proxy) ) {
|
||||
result = Py_nsISupports::PyObjectFromInterface(presult, iid, PR_FALSE);
|
||||
} else {
|
||||
result = PyXPCOM_BuildPyException(rv_proxy);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PyObject *AllocateBuffer(PyObject *self, PyObject *args)
|
||||
{
|
||||
int bufSize;
|
||||
if (!PyArg_ParseTuple(args, "i", &bufSize))
|
||||
return NULL;
|
||||
return PyBuffer_New(bufSize);
|
||||
}
|
||||
|
||||
PyObject *LogWarning(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *msg;
|
||||
if (!PyArg_ParseTuple(args, "s", &msg))
|
||||
return NULL;
|
||||
PyXPCOM_LogWarning("%s", msg);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *LogError(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *msg;
|
||||
if (!PyArg_ParseTuple(args, "s", &msg))
|
||||
return NULL;
|
||||
PyXPCOM_LogError("%s", msg);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
extern PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args);
|
||||
|
||||
static struct PyMethodDef xpcom_methods[]=
|
||||
{
|
||||
{"NS_LocateSpecialSystemDirectory", PyXPCOMMethod_NS_LocateSpecialSystemDirectory, 1},
|
||||
{"NS_GetGlobalComponentManager", PyXPCOMMethod_NS_GetGlobalComponentManager, 1},
|
||||
{"NS_NewFileSpec", PyXPCOMMethod_NS_NewFileSpec, 1},
|
||||
{"XPTI_GetInterfaceInfoManager", PyXPCOMMethod_XPTI_GetInterfaceInfoManager, 1},
|
||||
{"XPTC_InvokeByIndex", PyXPCOMMethod_XPTC_InvokeByIndex, 1},
|
||||
{"GetGlobalServiceManager", PyXPCOMMethod_GetGlobalServiceManager, 1},
|
||||
{"IID", PyXPCOMMethod_IID, 1}, // IID is wrong - deprecated - not just IID, but CID, etc.
|
||||
{"ID", PyXPCOMMethod_IID, 1}, // This is the official name.
|
||||
{"NS_ShutdownXPCOM", PyXPCOMMethod_NS_ShutdownXPCOM, 1},
|
||||
{"WrapObject", PyXPCOMMethod_WrapObject, 1},
|
||||
{"_GetInterfaceCount", PyXPCOMMethod_GetInterfaceCount, 1},
|
||||
{"_GetGatewayCount", PyXPCOMMethod_GetGatewayCount, 1},
|
||||
{"getProxyForObject", PyXPCOMMethod_GetProxyForObject, 1},
|
||||
{"GetProxyForObject", PyXPCOMMethod_GetProxyForObject, 1},
|
||||
{"AllocateBuffer", AllocateBuffer, 1},
|
||||
{"LogWarning", LogWarning, 1},
|
||||
{"LogError", LogError, 1},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Other helpers/global functions.
|
||||
//
|
||||
PRBool PyXPCOM_Globals_Ensure()
|
||||
{
|
||||
PRBool rc = PR_TRUE;
|
||||
|
||||
PyXPCOM_InterpreterState_Ensure();
|
||||
|
||||
// The exception object - we load it from .py code!
|
||||
if (PyXPCOM_Error == NULL) {
|
||||
rc = PR_FALSE;
|
||||
PyObject *mod = NULL;
|
||||
|
||||
mod = PyImport_ImportModule("xpcom");
|
||||
if (mod!=NULL) {
|
||||
PyXPCOM_Error = PyObject_GetAttrString(mod, "Exception");
|
||||
Py_DECREF(mod);
|
||||
}
|
||||
rc = (PyXPCOM_Error != NULL);
|
||||
}
|
||||
if (!rc)
|
||||
return rc;
|
||||
|
||||
static PRBool bHaveInitXPCOM = PR_FALSE;
|
||||
if (!bHaveInitXPCOM) {
|
||||
nsCOMPtr<nsIThread> thread_check;
|
||||
// xpcom appears to assert if already initialized
|
||||
// Is there an official way to determine this?
|
||||
if (NS_FAILED(nsIThread::GetMainThread(getter_AddRefs(thread_check)))) {
|
||||
// not already initialized.
|
||||
|
||||
// We need to locate the Mozilla bin directory.
|
||||
#ifdef XP_WIN
|
||||
// On Windows this by using "xpcom.dll"
|
||||
|
||||
char landmark[MAX_PATH+1];
|
||||
HMODULE hmod = GetModuleHandle("xpcom.dll");
|
||||
if (hmod==NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "We dont appear to be linked against xpcom.dll!?!?");
|
||||
return PR_FALSE;
|
||||
}
|
||||
GetModuleFileName(hmod, landmark, sizeof(landmark)/sizeof(landmark[0]));
|
||||
char *end = landmark + (strlen(landmark)-1);
|
||||
while (end > landmark && *end != '\\')
|
||||
end--;
|
||||
if (end > landmark) *end = '\0';
|
||||
|
||||
nsCOMPtr<nsILocalFile> ns_bin_dir;
|
||||
NS_NewLocalFile(landmark, PR_FALSE, getter_AddRefs(ns_bin_dir));
|
||||
nsresult rv = NS_InitXPCOM(nsnull, ns_bin_dir);
|
||||
#else
|
||||
// Elsewhere, Mozilla can find it itself (we hope!)
|
||||
nsresult rv = NS_InitXPCOM(nsnull, nsnull);
|
||||
#endif // XP_WIN
|
||||
if (NS_FAILED(rv)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "The XPCOM subsystem could not be initialized");
|
||||
return PR_FALSE;
|
||||
}
|
||||
// Also set the "special directory"
|
||||
#ifdef XP_WIN
|
||||
nsFileSpec spec(landmark);
|
||||
nsSpecialSystemDirectory::Set(nsSpecialSystemDirectory::OS_CurrentProcessDirectory, &spec);
|
||||
#endif // XP_WIN
|
||||
}
|
||||
// Even if xpcom was already init, we want to flag it as init!
|
||||
bHaveInitXPCOM = PR_TRUE;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#define REGISTER_IID(t) { \
|
||||
PyObject *iid_ob = Py_nsIID::PyObjectFromIID(NS_GET_IID(t)); \
|
||||
PyDict_SetItemString(dict, "IID_"#t, iid_ob); \
|
||||
Py_DECREF(iid_ob); \
|
||||
}
|
||||
|
||||
#define REGISTER_INT(val) { \
|
||||
PyObject *ob = PyInt_FromLong(val); \
|
||||
PyDict_SetItemString(dict, #val, ob); \
|
||||
Py_DECREF(ob); \
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// The module init code.
|
||||
//
|
||||
extern "C"
|
||||
#ifdef MS_WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void
|
||||
init_xpcom() {
|
||||
PyObject *oModule;
|
||||
|
||||
// ensure the framework has valid state to work with.
|
||||
if (!PyXPCOM_Globals_Ensure())
|
||||
return;
|
||||
|
||||
// Must force Python to start using thread locks
|
||||
PyEval_InitThreads();
|
||||
|
||||
// Create the module and add the functions
|
||||
oModule = Py_InitModule("_xpcom", xpcom_methods);
|
||||
|
||||
PyObject *dict = PyModule_GetDict(oModule);
|
||||
PyObject *pycom_Error = PyXPCOM_Error;
|
||||
if (pycom_Error == NULL || PyDict_SetItemString(dict, "error", pycom_Error) != 0)
|
||||
{
|
||||
PyErr_SetString(PyExc_MemoryError, "can't define error");
|
||||
return;
|
||||
}
|
||||
PyDict_SetItemString(dict, "IIDType", (PyObject *)&Py_nsIID::type);
|
||||
|
||||
REGISTER_IID(nsISupports);
|
||||
REGISTER_IID(nsISupportsString);
|
||||
REGISTER_IID(nsIModule);
|
||||
REGISTER_IID(nsIFactory);
|
||||
REGISTER_IID(nsIWeakReference);
|
||||
REGISTER_IID(nsISupportsWeakReference);
|
||||
// Register our custom interfaces.
|
||||
|
||||
Py_nsISupports::InitType();
|
||||
Py_nsIComponentManager::InitType(dict);
|
||||
Py_nsIInterfaceInfoManager::InitType(dict);
|
||||
Py_nsIEnumerator::InitType(dict);
|
||||
Py_nsISimpleEnumerator::InitType(dict);
|
||||
Py_nsIInterfaceInfo::InitType(dict);
|
||||
Py_nsIServiceManager::InitType(dict);
|
||||
Py_nsIInputStream::InitType(dict);
|
||||
|
||||
// We have special support for proxies - may as well add their constants!
|
||||
REGISTER_INT(PROXY_SYNC);
|
||||
REGISTER_INT(PROXY_ASYNC);
|
||||
REGISTER_INT(PROXY_ALWAYS);
|
||||
}
|
||||
Reference in New Issue
Block a user