Merge extensions/python/xpcom changes from DOM_AGNOSTIC2_BRANCH into the

trunk.


git-svn-id: svn://10.0.0.236/trunk@187878 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
mhammond%skippinet.com.au
2006-01-20 05:50:28 +00:00
parent 28dfbf4814
commit d394dc834d
56 changed files with 1710 additions and 958 deletions

View File

@@ -55,81 +55,179 @@ 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)
// Only used in really bad situations!
static void _PanicErrorWrite(const char *msg)
{
nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
NS_ABORT_IF_FALSE(consoleService, "Where is the console service?");
if (consoleService)
consoleService->LogStringMessage(NS_ConvertASCIItoUCS2(pszMessageText).get());
else
PR_fprintf(PR_STDERR,"%s\n", pszMessageText);
consoleService->LogStringMessage(NS_ConvertASCIItoUCS2(msg).get());
PR_fprintf(PR_STDERR,"%s\n", msg);
}
void LogMessage(const char *prefix, nsACString &text)
// Called when our "normal" error logger fails.
static void HandleLogError(const char *pszMessageText)
{
nsCAutoString streamout;
_PanicErrorWrite("Failed to log an error record");
if (PyXPCOM_FormatCurrentException(streamout))
_PanicErrorWrite(streamout.get());
_PanicErrorWrite("Original error follows:");
_PanicErrorWrite(pszMessageText);
}
static const char *LOGGER_WARNING = "warning";
static const char *LOGGER_ERROR = "error";
static const char *LOGGER_DEBUG = "debug";
// Our "normal" error logger - calls back to the logging module.
void DoLogMessage(const char *methodName, const char *pszMessageText)
{
// We use the logging module now. Originally this code called
// the logging module directly by way of the C API's
// PyImport_ImportModule/PyObject_CallMethod etc. However, this
// causes problems when there is no Python caller on the stack -
// the logging module's findCaller method fails with a None frame.
// We now work around this by calling PyRun_SimpleString - this
// causes a new frame to be created for executing the compiled
// string, and the logging module no longer fails.
// XXX - this implementation is less than ideal - findCaller now
// returns ("<string>", 2). Ideally we would compile with a
// filename something similar to "<pydom error reporter>".
// But this also means we need a clear error state...
PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
// We will execute:
// import logging
// logging.getLogger('xpcom').{warning/error/etc}("%s", {msg_text})
nsCAutoString c("import logging\nlogging.getLogger('xpcom').");
c += methodName;
c += "('%s', ";
// Pull a trick to ensure a valid string - use Python repr!
PyObject *obMessage = PyString_FromString(pszMessageText);
if (obMessage) {
PyObject *repr = PyObject_Repr(obMessage);
if (repr) {
c += PyString_AsString(repr);
Py_DECREF(repr);
}
Py_DECREF(obMessage);
}
c += ")\n";
if (PyRun_SimpleString(c.get()) != 0) {
HandleLogError(pszMessageText);
}
PyErr_Restore(exc_typ, exc_val, exc_tb);
}
void LogMessage(const char *methodName, const char *pszMessageText)
{
// Be careful to save and restore the Python exception state
// before calling back to Python, or we lose the original error.
PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
DoLogMessage(methodName, pszMessageText);
PyErr_Restore(exc_typ, exc_val, exc_tb);
}
void LogMessage(const char *methodName, nsACString &text)
{
char *c = ToNewCString(text);
LogMessage(prefix, c);
LogMessage(methodName, c);
nsCRT::free(c);
}
// A helper for the various logging routines.
static void VLogF(const char *prefix, const char *fmt, va_list argptr)
static void VLogF(const char *methodName, const char *fmt, va_list argptr)
{
char buff[512];
// Use safer NS_ functions.
PR_vsnprintf(buff, sizeof(buff), fmt, argptr);
vsprintf(buff, fmt, argptr);
LogMessage(methodName, buff);
}
LogMessage(prefix, buff);
PRBool PyXPCOM_FormatCurrentException(nsCString &streamout)
{
PRBool ok = PR_FALSE;
PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
PyErr_NormalizeException( &exc_typ, &exc_val, &exc_tb);
if (exc_typ) {
ok = PyXPCOM_FormatGivenException(streamout, exc_typ, exc_val,
exc_tb);
}
PyErr_Restore(exc_typ, exc_val, exc_tb);
return ok;
}
PRBool PyXPCOM_FormatGivenException(nsCString &streamout,
PyObject *exc_typ, PyObject *exc_val,
PyObject *exc_tb)
{
if (!exc_typ)
return PR_FALSE;
streamout += "\n";
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((void *)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!";
}
return PR_TRUE;
}
void PyXPCOM_LogError(const char *fmt, ...)
{
va_list marker;
va_start(marker, fmt);
VLogF("PyXPCOM Error: ", fmt, marker);
// NOTE: It is tricky to use logger.exception here - the exception
// state when called back from the C code is clear. Only Python 2.4
// and later allows an explicit exc_info tuple().
// Don't use VLogF here, instead arrange for exception info and
// traceback to be in the same buffer.
char buff[512];
PR_vsnprintf(buff, sizeof(buff), 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);
nsCAutoString streamout;
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((void *)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:", streamout);
nsCAutoString streamout(buff);
if (PyXPCOM_FormatCurrentException(streamout)) {
LogMessage(LOGGER_ERROR, streamout);
}
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);
VLogF(LOGGER_WARNING, fmt, marker);
}
void PyXPCOM_Log(const char *level, const nsCString &msg)
{
DoLogMessage(level, msg.get());
}
#ifdef DEBUG
@@ -137,7 +235,7 @@ void PyXPCOM_LogDebug(const char *fmt, ...)
{
va_list marker;
va_start(marker, fmt);
VLogF("PyXPCOM Debug: ", fmt, marker);
VLogF(LOGGER_DEBUG, fmt, marker);
}
#endif
@@ -156,7 +254,17 @@ nsresult PyXPCOM_SetCOMErrorFromPyException()
if (!PyErr_Occurred())
// No error occurred
return NS_OK;
return NS_ERROR_FAILURE;
nsresult rv = NS_ERROR_FAILURE;
if (PyErr_ExceptionMatches(PyExc_MemoryError))
rv = NS_ERROR_OUT_OF_MEMORY;
// todo:
// * Set an exception using the exception service.
// Once we have returned to the xpcom caller, we don't want to leave a
// Python exception pending - it may get noticed when the next call
// is made on the same thread.
PyErr_Clear();
return rv;
}
/* Obtains a string from a Python traceback.

View File

@@ -43,22 +43,23 @@ srcdir = @srcdir@
VPATH = @srcdir@
pyexecdir = @libdir@/python$(PYTHON_VER_DOTTED)/site-packages
DIRS = loader $(NULL)
DIRS = module loader $(NULL)
include $(DEPTH)/config/autoconf.mk
MODULE = pyxpcom
LIBRARY_NAME = _xpcom$(PYTHON_DEBUG_SUFFIX)
LIBRARY_NAME = pyxpcom
#MODULE_NAME =
REQUIRES = xpcom string $(NULL)
MOZILLA_INTERNAL_API = 1
FORCE_SHARED_LIB = 1
FORCE_USE_PIC = 1
DLL_SUFFIX=$(PYTHON_DLL_SUFFIX)
LOCAL_INCLUDES = $(PYTHON_INCLUDES)
EXTRA_LIBS += $(PYTHON_LIBS)
EXPORTS = PyXPCOM.h
CPPSRCS= \
ErrorUtils.cpp \
PyGBase.cpp \
@@ -80,33 +81,18 @@ CPPSRCS= \
TypeObject.cpp \
VariantUtils.cpp \
dllmain.cpp \
xpcom.cpp \
$(NULL)
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/config/rules.mk
EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
IMPORT_LIBRARY := $(SHARED_LIBRARY:.pyd=.lib)
# Install into our Python directory
# default build installs into bin and lib - remove them
libs::
ifeq ($(OS_ARCH),WINNT)
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(DIST)/bin/python/xpcom
ifeq ($(OS_ARCH),Darwin)
# Don't use the EXTRA_DSO_LDOPTS from rules.mk, it breaks the python module
EXTRA_DSO_LDOPTS = -bundle $(MOZ_COMPONENT_LIBS)
else
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(DIST)/bin/python/xpcom
mv $(DIST)/bin/python/xpcom/$(SHARED_LIBRARY) $(DIST)/bin/python/xpcom/_xpcom.so
endif
rm -f $(DIST)/bin/$(SHARED_LIBRARY)
rm -f $(DIST)/lib/$(IMPORT_LIBRARY)
install::
ifneq ($(OS_ARCH),WINNT)
$(SYSINSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(DISTDIR)$(pyexecdir)/xpcom
mv $(DISTDIR)$(pyexecdir)/xpcom/$(SHARED_LIBRARY) $(DISTDIR)$(pyexecdir)/xpcom/_xpcom$(PYTHON_DLL_SUFFIX)
EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
endif
clobber::
rm -f *.ilk *.pdb
rm -f *.ilk *.pdb *.exp *.lib *.pyd

View File

@@ -271,8 +271,18 @@ PyG_Base::MakeInterfaceParam(nsISupports *pis,
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 we don't know the IID, we must explicitly query for nsISupports.
nsCOMPtr<nsISupports> piswrap;
nsIID iid_check;
if (piid) {
iid_check = *piid;
piswrap = pis;
} else {
iid_check = NS_GET_IID(nsISupports);
pis->QueryInterface(iid_check, getter_AddRefs(piswrap));
}
obISupports = Py_nsISupports::PyObjectFromInterface(piswrap, iid_check, PR_FALSE);
if (!obISupports)
goto done;
if (piid==NULL) {
@@ -346,7 +356,11 @@ PyG_Base::QueryInterface(REFNSIID iid, void** ppv)
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);
// must say this is an 'internal' call, else we recurse QI into
// oblivion.
PyObject * this_interface_ob = Py_nsISupports::PyObjectFromInterface(
(nsXPTCStubBase *)this,
iid, PR_FALSE, PR_TRUE);
if ( !ob || !this_interface_ob) {
Py_XDECREF(ob);
Py_XDECREF(this_interface_ob);
@@ -355,7 +369,7 @@ PyG_Base::QueryInterface(REFNSIID iid, void** ppv)
PyObject *result = PyObject_CallMethod(m_pPyObject, "_QueryInterface_",
"OO",
this_interface_ob, ob);
this_interface_ob, ob);
Py_DECREF(ob);
Py_DECREF(this_interface_ob);
@@ -426,6 +440,7 @@ PyG_Base::GetWeakReference(nsIWeakReference **ret)
if (ret==nsnull) return NS_ERROR_INVALID_POINTER;
if (!m_pWeakRef) {
// First query for a weak reference - create it.
// XXX - this looks like it needs thread safety!?
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)
@@ -444,17 +459,17 @@ nsresult PyG_Base::HandleNativeGatewayError(const char *szMethodName)
// 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
// exited, 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)
// is no Python function directly 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.
// 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;
@@ -696,10 +711,10 @@ PyObject *PyG_Base::UnwrapPythonObject(void)
Some special support to help with object identity.
In the simplest case, assume a Python COM object is
In the simplest case, assume a Python XPCOM object is
supporting a function "nsIWhatever GetWhatever()",
so implements it as:
return this
return self
it is almost certain they intend returning
the same COM OBJECT to the caller! Thus, if a user of this COM
object does:
@@ -709,7 +724,7 @@ PyObject *PyG_Base::UnwrapPythonObject(void)
We almost certainly expect p1==p2==foo.
We previously _did_ have special support for the "this"
We previously _did_ have special support for the "self"
example above, but this implements a generic scheme that
works for _all_ objects.
@@ -803,12 +818,11 @@ void AddDefaultGateway(PyObject *instance, nsISupports *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 );
nsCOMPtr<nsIWeakReference> pWeakReference;
swr->GetWeakReference( getter_AddRefs(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) {

View File

@@ -80,7 +80,7 @@ PyG_nsIModule::GetClassObject(nsIComponentManager *aCompMgr,
NS_PRECONDITION(r_classObj, "null pointer");
*r_classObj = nsnull;
CEnterLeavePython _celp;
PyObject *cm = Py_nsISupports::PyObjectFromInterface(aCompMgr, NS_GET_IID(nsIComponentManager), PR_TRUE);
PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager));
PyObject *iid = Py_nsIID::PyObjectFromIID(aIID);
PyObject *clsid = Py_nsIID::PyObjectFromIID(aClass);
const char *methodName = "getClassObject";
@@ -110,8 +110,8 @@ PyG_nsIModule::RegisterSelf(nsIComponentManager *aCompMgr,
NS_PRECONDITION(aCompMgr, "null pointer");
NS_PRECONDITION(aPath, "null pointer");
CEnterLeavePython _celp;
PyObject *cm = Py_nsISupports::PyObjectFromInterface(aCompMgr, NS_GET_IID(nsIComponentManager), PR_TRUE);
PyObject *path = Py_nsISupports::PyObjectFromInterface(aPath, NS_GET_IID(nsIFile), PR_TRUE);
PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager));
PyObject *path = PyObject_FromNSInterface(aPath, NS_GET_IID(nsIFile));
const char *methodName = "registerSelf";
nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OOzz", cm, path, registryLocation, componentType);
Py_XDECREF(cm);
@@ -127,8 +127,8 @@ PyG_nsIModule::UnregisterSelf(nsIComponentManager* aCompMgr,
NS_PRECONDITION(aCompMgr, "null pointer");
NS_PRECONDITION(aPath, "null pointer");
CEnterLeavePython _celp;
PyObject *cm = Py_nsISupports::PyObjectFromInterface(aCompMgr, NS_GET_IID(nsIComponentManager), PR_TRUE);
PyObject *path = Py_nsISupports::PyObjectFromInterface(aPath, NS_GET_IID(nsIFile), PR_TRUE);
PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager));
PyObject *path = PyObject_FromNSInterface(aPath, NS_GET_IID(nsIFile));
const char *methodName = "unregisterSelf";
nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OOz", cm, path, registryLocation);
Py_XDECREF(cm);
@@ -143,7 +143,7 @@ PyG_nsIModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload)
NS_PRECONDITION(okToUnload, "null pointer");
CEnterLeavePython _celp;
// we are shutting down - don't ask for a nice wrapped object.
PyObject *cm = Py_nsISupports::PyObjectFromInterface(aCompMgr, NS_GET_IID(nsIComponentManager), PR_TRUE, PR_FALSE);
PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager), PR_FALSE);
const char *methodName = "canUnload";
PyObject *ret = NULL;
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "O", cm);

View File

@@ -96,7 +96,8 @@ PyXPCOM_XPTStub::CallMethod(PRUint16 methodIndex,
if (obMI==NULL)
goto done;
// base object is passed raw.
obThisObject = Py_nsISupports::PyObjectFromInterface((nsIInternalPython*)this, NS_GET_IID(nsISupports), PR_TRUE, PR_FALSE);
obThisObject = PyObject_FromNSInterface((nsXPTCStubBase *)this,
m_iid, PR_FALSE);
obParams = arg_helper.MakePyArgs();
if (obParams==NULL)
goto done;

View File

@@ -93,14 +93,14 @@ static PyObject *PyGetHelperForLanguage(PyObject *self, PyObject *args)
return NULL;
nsresult r;
nsISupports *pi;
nsCOMPtr<nsISupports> pi;
Py_BEGIN_ALLOW_THREADS;
r = pI->GetHelperForLanguage(language, &pi);
r = pI->GetHelperForLanguage(language, getter_AddRefs(pi));
Py_END_ALLOW_THREADS;
if ( NS_FAILED(r) )
return PyXPCOM_BuildPyException(r);
return Py_nsISupports::PyObjectFromInterface(pi, NS_GET_IID(nsISupports), PR_FALSE);
return Py_nsISupports::PyObjectFromInterface(pi, NS_GET_IID(nsISupports));
}
static PyObject *MakeStringOrNone(char *v)

View File

@@ -81,16 +81,16 @@ static PyObject *PyCreateInstanceByContractID(PyObject *self, PyObject *args)
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
return NULL;
nsISupports *pis;
nsCOMPtr<nsISupports> pis;
nsresult r;
Py_BEGIN_ALLOW_THREADS;
r = pI->CreateInstanceByContractID(pid, NULL, iid, (void **)&pis);
r = pI->CreateInstanceByContractID(pid, NULL, iid, getter_AddRefs(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, PR_FALSE);
return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE);
}
static PyObject *PyCreateInstance(PyObject *self, PyObject *args)
@@ -117,16 +117,16 @@ static PyObject *PyCreateInstance(PyObject *self, PyObject *args)
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
return NULL;
nsISupports *pis;
nsCOMPtr<nsISupports> pis;
nsresult r;
Py_BEGIN_ALLOW_THREADS;
r = pI->CreateInstance(classID, NULL, iid, (void **)&pis);
r = pI->CreateInstance(classID, NULL, iid, getter_AddRefs(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, PR_FALSE);
return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE);
}
struct PyMethodDef

View File

@@ -121,7 +121,9 @@ static PyObject *PyCurrentItem(PyObject *self, PyObject *args)
}
pRet = temp;
}
return Py_nsISupports::PyObjectFromInterface(pRet, iid, PR_FALSE);
PyObject *ret = Py_nsISupports::PyObjectFromInterface(pRet, iid);
NS_IF_RELEASE(pRet);
return ret;
}
// A method added for Python performance if you really need
@@ -179,7 +181,8 @@ static PyObject *PyFetchBlock(PyObject *self, PyObject *args)
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);
PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid);
NS_IF_RELEASE(fetched[i]);
PyList_SET_ITEM(ret, i, new_ob);
}
} else

View File

@@ -54,7 +54,7 @@
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)
PYXPCOM_EXPORT PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args)
{
PyObject *obIID;
PyObject *obBuf;

View File

@@ -128,14 +128,14 @@ static PyObject *PyGetParent(PyObject *self, PyObject *args)
if (pI==NULL)
return NULL;
nsIInterfaceInfo *pRet;
nsCOMPtr<nsIInterfaceInfo> pRet;
nsresult r;
Py_BEGIN_ALLOW_THREADS;
r = pI->GetParent(&pRet);
r = pI->GetParent(getter_AddRefs(pRet));
Py_END_ALLOW_THREADS;
if ( NS_FAILED(r) )
return PyXPCOM_BuildPyException(r);
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIInterfaceInfo), PR_FALSE, PR_FALSE);
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIInterfaceInfo), PR_FALSE);
}
static PyObject *PyGetMethodCount(PyObject *self, PyObject *args)
@@ -288,11 +288,11 @@ static PyObject *PyGetInfoForParam(PyObject *self, PyObject *args)
if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
return NULL;
const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
nsIInterfaceInfo *pnewii = nsnull;
nsresult n = pii->GetInfoForParam(mi, &param_info, &pnewii);
nsCOMPtr<nsIInterfaceInfo> pnewii;
nsresult n = pii->GetInfoForParam(mi, &param_info, getter_AddRefs(pnewii));
if (NS_FAILED(n))
return PyXPCOM_BuildPyException(n);
return Py_nsISupports::PyObjectFromInterface(pnewii, NS_GET_IID(nsIInterfaceInfo), PR_FALSE);
return Py_nsISupports::PyObjectFromInterface(pnewii, NS_GET_IID(nsIInterfaceInfo));
}
static PyObject *PyGetIIDForParam(PyObject *self, PyObject *args)

View File

@@ -73,10 +73,10 @@ static PyObject *PyGetInfoForIID(PyObject *self, PyObject *args)
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
return NULL;
nsIInterfaceInfo *pi;
nsCOMPtr<nsIInterfaceInfo> pi;
nsresult r;
Py_BEGIN_ALLOW_THREADS;
r = pI->GetInfoForIID(&iid, &pi);
r = pI->GetInfoForIID(&iid, getter_AddRefs(pi));
Py_END_ALLOW_THREADS;
if ( NS_FAILED(r) )
return PyXPCOM_BuildPyException(r);
@@ -85,7 +85,7 @@ static PyObject *PyGetInfoForIID(PyObject *self, PyObject *args)
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);
return Py_nsISupports::PyObjectFromInterface(pi, new_iid, PR_FALSE);
}
static PyObject *PyGetInfoForName(PyObject *self, PyObject *args)
@@ -98,10 +98,10 @@ static PyObject *PyGetInfoForName(PyObject *self, PyObject *args)
if (pI==NULL)
return NULL;
nsIInterfaceInfo *pi;
nsCOMPtr<nsIInterfaceInfo> pi;
nsresult r;
Py_BEGIN_ALLOW_THREADS;
r = pI->GetInfoForName(name, &pi);
r = pI->GetInfoForName(name, getter_AddRefs(pi));
Py_END_ALLOW_THREADS;
if ( NS_FAILED(r) )
return PyXPCOM_BuildPyException(r);
@@ -109,7 +109,7 @@ static PyObject *PyGetInfoForName(PyObject *self, PyObject *args)
/* 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);
return Py_nsISupports::PyObjectFromInterface(pi, NS_GET_IID(nsIInterfaceInfo), PR_FALSE);
}
static PyObject *PyGetNameForIID(PyObject *self, PyObject *args)
@@ -171,15 +171,15 @@ static PyObject *PyEnumerateInterfaces(PyObject *self, PyObject *args)
if (pI==NULL)
return NULL;
nsIEnumerator *pRet;
nsCOMPtr<nsIEnumerator> pRet;
nsresult r;
Py_BEGIN_ALLOW_THREADS;
r = pI->EnumerateInterfaces(&pRet);
r = pI->EnumerateInterfaces(getter_AddRefs(pRet));
Py_END_ALLOW_THREADS;
if ( NS_FAILED(r) )
return PyXPCOM_BuildPyException(r);
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator), PR_FALSE);
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator));
}
// TODO:

View File

@@ -109,7 +109,9 @@ static PyObject *PyGetNext(PyObject *self, PyObject *args)
}
pRet = temp;
}
return Py_nsISupports::PyObjectFromInterface(pRet, iid, PR_FALSE);
PyObject *ret = Py_nsISupports::PyObjectFromInterface(pRet, iid);
NS_IF_RELEASE(pRet);
return ret;
}
// A method added for Python performance if you really need
@@ -169,7 +171,8 @@ static PyObject *PyFetchBlock(PyObject *self, PyObject *args)
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);
PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid);
NS_IF_RELEASE(fetched[i]);
PyList_SET_ITEM(ret, i, new_ob);
}
} else

View File

@@ -46,10 +46,19 @@
// (c) 2000, ActiveState corp.
#include "PyXPCOM_std.h"
#include "nsISupportsPrimitives.h"
static PRInt32 cInterfaces=0;
static PyObject *g_obFuncMakeInterfaceCount = NULL; // XXX - never released!!!
PyObject *PyObject_FromNSInterface( nsISupports *aInterface,
const nsIID &iid,
PRBool bMakeNicePyObject /*= PR_TRUE */)
{
return Py_nsISupports::PyObjectFromInterface(aInterface, iid,
bMakeNicePyObject);
}
PRInt32
_PyXPCOM_GetInterfaceCount(void)
{
@@ -99,15 +108,9 @@ Py_nsISupports::SafeRelease(Py_nsISupports *ob)
return;
if (ob->m_obj)
{
long rcnt;
Py_BEGIN_ALLOW_THREADS;
rcnt = ob->m_obj->Release();
ob->m_obj = nsnull;
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;
}
}
@@ -117,6 +120,23 @@ Py_nsISupports::getattr(const char *name)
if (strcmp(name, "IID")==0)
return Py_nsIID::PyObjectFromIID( m_iid );
// Support for __unicode__ until we get a tp_unicode slot.
if (strcmp(name, "__unicode__")==0) {
nsresult rv;
PRUnichar *val = NULL;
Py_BEGIN_ALLOW_THREADS;
{ // scope to kill pointer while thread-lock released.
nsCOMPtr<nsISupportsString> ss( do_QueryInterface(m_obj, &rv ));
if (NS_SUCCEEDED(rv))
rv = ss->ToString(&val);
} // end-scope
Py_END_ALLOW_THREADS;
PyObject *ret = NS_FAILED(rv) ?
PyXPCOM_BuildPyException(rv) :
PyObject_FromNSString(val);
if (val) nsMemory::Free(val);
return ret;
}
PyXPCOM_TypeObject *this_type = (PyXPCOM_TypeObject *)ob_type;
return Py_FindMethodInChain(&this_type->chain, this, (char *)name);
}
@@ -231,8 +251,13 @@ Py_nsISupports::InterfaceFromPyObject(PyObject *ob,
Py_DECREF(sub_ob);
}
}
*ppv = PyObject_AsVariant(ob);
return *ppv != NULL;
nsresult nr = PyObject_AsVariant(ob, (nsIVariant **)ppv);
if (NS_FAILED(nr)) {
PyXPCOM_BuildPyException(nr);
return PR_FALSE;
}
NS_ASSERTION(ppv != nsnull, "PyObject_AsVariant worked but gave null!");
return PR_TRUE;
}
// end of variant support.
@@ -273,33 +298,11 @@ Py_nsISupports::RegisterInterface( const nsIID &iid, PyTypeObject *t)
}
}
/*static */PyObject *
Py_nsISupports::PyObjectFromInterfaceOrVariant(nsISupports *pis,
const nsIID &riid,
PRBool bAddRef,
PRBool bMakeNicePyObject /* = PR_TRUE */)
{
// Quick exit.
if (pis==NULL) {
Py_INCREF(Py_None);
return Py_None;
}
if (riid.Equals(NS_GET_IID(nsIVariant))) {
PyObject *ret = PyObject_FromVariant((nsIVariant *)pis);
// If we were asked not to add a reference, then there
// will be a spare reference on pis() - remove it.
if (!bAddRef)
pis->Release();
return ret;
}
return PyObjectFromInterface(pis, riid, bAddRef, bMakeNicePyObject);
}
/*static */PyObject *
Py_nsISupports::PyObjectFromInterface(nsISupports *pis,
const nsIID &riid,
PRBool bAddRef,
PRBool bMakeNicePyObject /* = PR_TRUE */)
PRBool bMakeNicePyObject, /* = PR_TRUE */
PRBool bIsInternalCall /* = PR_FALSE */)
{
// Quick exit.
if (pis==NULL) {
@@ -307,9 +310,15 @@ Py_nsISupports::PyObjectFromInterface(nsISupports *pis,
return Py_None;
}
// FIXME: if !bAddRef, in all error cases, do NS_RELEASE(pis) before return
// since that means we have a spare reference
if (!bIsInternalCall) {
#ifdef NS_DEBUG
nsISupports *queryResult = nsnull;
pis->QueryInterface(riid, (void **)&queryResult);
NS_ASSERTION(queryResult == pis, "QueryInterface needed");
NS_IF_RELEASE(queryResult);
#endif
}
PyTypeObject *createType = NULL;
// If the IID is for nsISupports, don't bother with
// a map lookup as we know the type!
@@ -341,16 +350,15 @@ Py_nsISupports::PyObjectFromInterface(nsISupports *pis,
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 MakeDefaultWrapper(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,
Py_nsISupports::MakeDefaultWrapper(PyObject *pyis,
const nsIID &iid)
{
NS_PRECONDITION(pyis, "NULL pyobject!");
@@ -411,10 +419,17 @@ Py_nsISupports::QueryInterface(PyObject *self, PyObject *args)
nsISupports *pMyIS = GetI(self);
if (pMyIS==NULL) return NULL;
nsISupports *pis;
// Optimization, If we already wrap the IID, just return
// ourself.
if (!bWrap && iid.Equals(((Py_nsISupports *)self)->m_iid)) {
Py_INCREF(self);
return self;
}
nsCOMPtr<nsISupports> pis;
nsresult r;
Py_BEGIN_ALLOW_THREADS;
r = pMyIS->QueryInterface(iid, (void **)&pis);
r = pMyIS->QueryInterface(iid, getter_AddRefs(pis));
Py_END_ALLOW_THREADS;
/* Note that this failure may include E_NOINTERFACE */
@@ -422,7 +437,7 @@ Py_nsISupports::QueryInterface(PyObject *self, PyObject *args)
return PyXPCOM_BuildPyException(r);
/* Return a type based on the IID (with no extra ref) */
return PyObjectFromInterface(pis, iid, PR_FALSE, (PRBool)bWrap);
return ((Py_nsISupports *)self)->MakeInterfaceResult(pis, iid, (PRBool)bWrap);
}

View File

@@ -64,13 +64,10 @@ static PyObject *MyChar( char c) {
return PyString_FromStringAndSize(&c, 1);
}
static PyObject *MyUChar( PRUnichar c) {
return PyUnicode_FromPRUnichar(&c, 1);
return PyObject_FromNSString( &c, 1);
}
static PyObject *MyUnicode( PRUnichar *p) {
return PyUnicode_FromPRUnichar(p, nsCRT::strlen(p));
}
static PyObject *MyISupports( nsISupports *p) {
return Py_nsISupports::PyObjectFromInterface(p, NS_GET_IID(nsISupports), PR_FALSE);
return PyObject_FromNSString(p);
}
#define GET_SIMPLE(Type, FuncGet, FuncConvert) \
@@ -123,32 +120,49 @@ GET_SIMPLE(double, GetAsDouble, PyFloat_FromDouble)
GET_SIMPLE(PRBool, GetAsBool, MyBool)
GET_SIMPLE(char, GetAsChar, MyChar)
GET_SIMPLE(PRUnichar, GetAsWChar, MyUChar)
GET_SIMPLE(nsISupports *, GetAsISupports, MyISupports)
GET_SIMPLE(nsIID, GetAsID, Py_nsIID::PyObjectFromIID)
GET_ALLOCATED(char *, GetAsString, PyString_FromString, nsMemory::Free)
GET_ALLOCATED(PRUnichar *, GetAsWString, MyUnicode, nsMemory::Free)
GET_ALLOCATED_SIZE(char *, GetAsStringWithSize, PyString_FromStringAndSize, nsMemory::Free)
GET_ALLOCATED_SIZE(PRUnichar *, GetAsWStringWithSize, PyUnicode_FromPRUnichar, nsMemory::Free)
GET_ALLOCATED_SIZE(PRUnichar *, GetAsWStringWithSize, PyObject_FromNSString, nsMemory::Free)
static PyObject *GetAsInterface(PyObject *self, PyObject *args) {
nsIVariant *pI = GetI(self);
if (pI==NULL) return NULL;
if (!PyArg_ParseTuple(args, ":GetAsInterface")) return NULL;
nsISupports *p;
nsCOMPtr<nsISupports> p;
nsIID *iid;
nsresult nr = pI->GetAsInterface(&iid, (void **)&p);
nsresult nr = pI->GetAsInterface(&iid, getter_AddRefs(p));
if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr);
return Py_nsISupports::PyObjectFromInterface(p, *iid, PR_FALSE);
return Py_nsISupports::PyObjectFromInterface(p, *iid);
}
extern PyObject *PyObject_FromVariantArray( nsIVariant *v);
static PyObject *GetAsISupports(PyObject *self, PyObject *args) {
nsIVariant *pI = GetI(self);
if (pI==NULL) return NULL;
if (!PyArg_ParseTuple(args, ":GetAsInterface")) return NULL;
nsCOMPtr<nsISupports> p;
nsIID *iid;
nsresult nr = pI->GetAsInterface(&iid, getter_AddRefs(p));
if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr);
return Py_nsISupports::PyObjectFromInterface(p, *iid);
}
extern PyObject *PyObject_FromVariantArray( Py_nsISupports*, nsIVariant *v);
static PyObject *GetAsArray(PyObject *self, PyObject *args) {
nsIVariant *pI = GetI(self);
if (pI==NULL) return NULL;
if (!PyArg_ParseTuple(args, ":GetAsArray")) return NULL;
return PyObject_FromVariantArray(pI);
return PyObject_FromVariantArray((Py_nsISupports *)self, pI);
}
static PyObject *Get(PyObject *self, PyObject *args) {
nsIVariant *pI = GetI(self);
if (pI==NULL) return NULL;
if (!PyArg_ParseTuple(args, ":Get")) return NULL;
return PyObject_FromVariant((Py_nsISupports *)self, pI);
}
struct PyMethodDef
@@ -175,6 +189,7 @@ PyMethods_IVariant[] =
{ "getAsInterface", GetAsInterface, 1},
{ "getAsArray", GetAsArray, 1},
{ "getAsID", GetAsID, 1},
{ "get", Get, 1},
{NULL}
};

View File

@@ -49,26 +49,46 @@
#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
#include "nsIAllocator.h"
#include "nsIWeakReference.h"
#include "nsIInterfaceInfoManager.h"
#include "nsIClassInfo.h"
#include "nsIComponentManager.h"
#include "nsIComponentManagerObsolete.h"
#include "nsIServiceManager.h"
#include "nsIInputStream.h"
#include "nsIVariant.h"
#include "nsIModule.h"
// We need these libs!
# pragma comment(lib, "xpcom.lib")
# pragma comment(lib, "nspr4.lib")
#include "nsXPIDLString.h"
#include "nsCRT.h"
#include "xptcall.h"
#include "xpt_xdr.h"
#else // XP_WIN
# define PYXPCOM_EXPORT
#endif // XP_WIN
#ifdef HAVE_LONG_LONG
// Mozilla also defines this - we undefine it to
// prevent a compiler warning.
# undef HAVE_LONG_LONG
#endif // HAVE_LONG_LONG
#ifdef _POSIX_C_SOURCE // Ditto here
# undef _POSIX_C_SOURCE
#endif // _POSIX_C_SOURCE
#include <Python.h>
#ifdef BUILD_PYXPCOM
/* We are building the main dll */
# define PYXPCOM_EXPORT NS_EXPORT
#else
/* This module uses the dll */
# define PYXPCOM_EXPORT NS_IMPORT
#endif // BUILD_PYXPCOM
// An IID we treat as NULL when passing as a reference.
extern nsIID Py_nsIID_NULL;
extern PYXPCOM_EXPORT nsIID Py_nsIID_NULL;
class Py_nsISupports;
/*************************************************************************
**************************************************************************
@@ -94,6 +114,13 @@ PYXPCOM_EXPORT PyObject *PyXPCOM_BuildPyException(nsresult res);
// NOTE: this function assumes it is operating within the Python context
PYXPCOM_EXPORT nsresult PyXPCOM_SetCOMErrorFromPyException();
// Write current exception and traceback to a string.
PYXPCOM_EXPORT PRBool PyXPCOM_FormatCurrentException(nsCString &streamout);
// Write specified exception and traceback to a string.
PYXPCOM_EXPORT PRBool PyXPCOM_FormatGivenException(nsCString &streamout,
PyObject *exc_typ, PyObject *exc_val,
PyObject *exc_tb);
// A couple of logging/error functions. These probably end up
// being written to the console service.
@@ -108,6 +135,9 @@ PYXPCOM_EXPORT void PyXPCOM_LogWarning(const char *fmt, ...);
// As it's designed for user error/warning, it exists in non-debug builds.
PYXPCOM_EXPORT void PyXPCOM_LogError(const char *fmt, ...);
// The raw one
PYXPCOM_EXPORT void PyXPCOM_Log(const char *level, const nsCString &msg);
#ifdef DEBUG
// Mainly designed for developers of the XPCOM package.
// Only enabled in debug builds.
@@ -117,9 +147,27 @@ PYXPCOM_EXPORT void PyXPCOM_LogDebug(const char *fmt, ...);
#define PYXPCOM_LOG_DEBUG()
#endif // DEBUG
// Create a Unicode Object from the PRUnichar buffer src of the given size
#define PyUnicode_FromPRUnichar(src, size) \
PyUnicode_DecodeUTF16((char*)(src),sizeof(PRUnichar)*(size),NULL,NULL)
// Some utility converters
// moz strings to PyObject.
PYXPCOM_EXPORT PyObject *PyObject_FromNSString( const nsACString &s,
PRBool bAssumeUTF8 = PR_FALSE );
PYXPCOM_EXPORT PyObject *PyObject_FromNSString( const nsAString &s );
PYXPCOM_EXPORT PyObject *PyObject_FromNSString( const PRUnichar *s,
PRUint32 len = (PRUint32)-1);
// PyObjects to moz strings. As per the moz string guide, we pass a reference
// to an abstract string
PYXPCOM_EXPORT PRBool PyObject_AsNSString( PyObject *ob, nsAString &aStr);
// Variants.
PYXPCOM_EXPORT nsresult PyObject_AsVariant( PyObject *ob, nsIVariant **aRet);
PYXPCOM_EXPORT PyObject *PyObject_FromVariant( Py_nsISupports *parent,
nsIVariant *v);
// Interfaces - these are the "official" functions
PYXPCOM_EXPORT PyObject *PyObject_FromNSInterface( nsISupports *aInterface,
const nsIID &iid,
PRBool bMakeNicePyObject = PR_TRUE);
/*************************************************************************
**************************************************************************
@@ -129,8 +177,6 @@ PYXPCOM_EXPORT void PyXPCOM_LogDebug(const char *fmt, ...);
**************************************************************************
*************************************************************************/
class Py_nsISupports;
typedef Py_nsISupports* (* PyXPCOM_I_CTOR)(nsISupports *, const nsIID &);
//////////////////////////////////////////////////////////////////////////
@@ -174,6 +220,9 @@ public:
class PYXPCOM_EXPORT Py_nsISupports : public PyObject
{
public:
// Check if a Python object can safely be cast to an Py_nsISupports,
// and optionally check that the object is wrapping the specified
// interface.
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 ))
@@ -184,31 +233,24 @@ public:
}
// Get the nsISupports interface from the PyObject WITH NO REF COUNT ADDED
static nsISupports *GetI(PyObject *self, nsIID *ret_iid = NULL);
nsISupports *m_obj;
nsCOMPtr<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. ***
// is really a pointer to an object identified by the IID (although
// debug builds should check this)
// 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.
// xpcom functions directly from C++.
// NOTE: There used to be a bAddRef param to this as an internal
// optimization, but since removed. This function *always* takes a
// reference to the nsISupports.
static PyObject *PyObjectFromInterface(nsISupports *ps,
const nsIID &iid,
PRBool bAddRef,
PRBool bMakeNicePyObject = PR_TRUE);
static PyObject *PyObjectFromInterfaceOrVariant(nsISupports *ps,
const nsIID &iid,
PRBool bAddRef,
PRBool bMakeNicePyObject = PR_TRUE);
PRBool bMakeNicePyObject = PR_TRUE,
PRBool bIsInternalCall = PR_FALSE);
// Given a Python object that is a registered COM type, return a given
// interface pointer on its underlying object, with a NEW REFERENCE ADDED.
@@ -238,8 +280,8 @@ public:
static PyObject *QueryInterface(PyObject *self, PyObject *args);
// Internal (sort-of) objects.
static PyXPCOM_TypeObject *type;
static PyMethodDef methods[];
static NS_EXPORT_STATIC_MEMBER_(PyXPCOM_TypeObject) *type;
static NS_EXPORT_STATIC_MEMBER_(PyMethodDef) methods[];
static PyObject *mapIIDToType;
static void SafeRelease(Py_nsISupports *ob);
static void RegisterInterface( const nsIID &iid, PyTypeObject *t);
@@ -248,6 +290,14 @@ public:
virtual ~Py_nsISupports();
virtual PyObject *getattr(const char *name);
virtual int setattr(const char *name, PyObject *val);
// A virtual function to sub-classes can customize the way
// nsISupports objects are returned from their methods.
// ps is a new object just obtained from some operation performed on us
virtual PyObject *MakeInterfaceResult(nsISupports *ps, const nsIID &iid,
PRBool bMakeNicePyObject = PR_TRUE) {
return PyObjectFromInterface(ps, iid, bMakeNicePyObject);
}
protected:
// ctor is protected - must create objects via
// PyObjectFromInterface()
@@ -255,7 +305,9 @@ protected:
const nsIID &iid,
PyTypeObject *type);
static PyObject *MakeInterfaceResult(PyObject *pyis, const nsIID &iid);
// Make a default wrapper for an ISupports (which is an
// xpcom.client.Component instance)
static PyObject *MakeDefaultWrapper(PyObject *pyis, const nsIID &iid);
};
@@ -296,8 +348,8 @@ public:
static long PyTypeMethod_hash(PyObject *self);
static PyObject *PyTypeMethod_str(PyObject *self);
static void PyTypeMethod_dealloc(PyObject *self);
static PyTypeObject type;
static PyMethodDef methods[];
static NS_EXPORT_STATIC_MEMBER_(PyTypeObject) type;
static NS_EXPORT_STATIC_MEMBER_(PyMethodDef) methods[];
};
///////////////////////////////////////////////////////
@@ -307,7 +359,7 @@ class PythonTypeDescriptor; // Forward declare.
class PYXPCOM_EXPORT PyXPCOM_InterfaceVariantHelper {
public:
PyXPCOM_InterfaceVariantHelper();
PyXPCOM_InterfaceVariantHelper(Py_nsISupports *parent);
~PyXPCOM_InterfaceVariantHelper();
PRBool Init(PyObject *obParams);
PRBool FillArray();
@@ -327,6 +379,7 @@ protected:
PyObject *m_typedescs; // desc of _all_ params, including hidden.
PythonTypeDescriptor *m_python_type_desc_array;
void **m_buffer_array;
Py_nsISupports *m_parent;
};
@@ -457,6 +510,11 @@ private:
return GATEWAY_BASE::ThisAsIID(iid); \
} \
extern PYXPCOM_EXPORT void AddDefaultGateway(PyObject *instance, nsISupports *gateway);
extern PYXPCOM_EXPORT PRInt32 _PyXPCOM_GetGatewayCount(void);
extern PYXPCOM_EXPORT PRInt32 _PyXPCOM_GetInterfaceCount(void);
// Weak Reference class. This is a true COM object, representing
// a weak reference to a Python object. For each Python XPCOM object,
@@ -496,7 +554,7 @@ 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);
nsresult GetArrayType(PRUint8 index, PRUint8 *ret, nsIID **ppiid);
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 );
@@ -520,9 +578,6 @@ PyObject *PyObject_FromXPTParamDescriptor( const XPTParamDescriptor *d);
PyObject *PyObject_FromXPTMethodDescriptor( const XPTMethodDescriptor *d);
PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *d);
nsIVariant *PyObject_AsVariant( PyObject *ob);
PyObject *PyObject_FromVariant( nsIVariant *v);
// DLL reference counting functions.
// Although we maintain the count, we never actually
// finalize Python when it hits zero!
@@ -579,8 +634,8 @@ public:
// NEVER new one of these objects - only use on the stack!
extern PYXPCOM_EXPORT void PyXPCOM_MakePendingCalls();
extern PYXPCOM_EXPORT PRBool PyXPCOM_Globals_Ensure();
PYXPCOM_EXPORT void PyXPCOM_MakePendingCalls();
PYXPCOM_EXPORT PRBool PyXPCOM_Globals_Ensure();
// For 2.3, use the PyGILState_ calls
#if (PY_VERSION_HEX >= 0x02030000)
@@ -605,12 +660,12 @@ public:
};
#else
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();
PYXPCOM_EXPORT PyInterpreterState *PyXPCOM_InterpreterState;
PYXPCOM_EXPORT PRBool PyXPCOM_ThreadState_Ensure();
PYXPCOM_EXPORT void PyXPCOM_ThreadState_Free();
PYXPCOM_EXPORT void PyXPCOM_ThreadState_Clear();
PYXPCOM_EXPORT void PyXPCOM_InterpreterLock_Acquire();
PYXPCOM_EXPORT void PyXPCOM_InterpreterLock_Release();
// Pre 2.3 thread-state dances.
class CEnterLeavePython {
@@ -662,11 +717,11 @@ extern struct PyMethodDef Methods[]; \
class ClassName : public Py_nsISupports \
{ \
public: \
static PyXPCOM_TypeObject *type; \
static PYXPCOM_EXPORT PyXPCOM_TypeObject *type; \
static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid) { \
return new ClassName(pInitObj, iid); \
} \
static void InitType(PyObject *iidNameDict) { \
static void InitType() { \
type = new PyXPCOM_TypeObject( \
#InterfaceName, \
Py_nsISupports::type, \
@@ -675,9 +730,6 @@ public: \
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) : \
@@ -700,7 +752,7 @@ public: \
static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid) { \
return new ClassName(pInitObj, iid); \
} \
static void InitType(PyObject *iidNameDict) { \
static void InitType() { \
type = new PyXPCOM_TypeObject( \
#InterfaceName, \
Py_nsISupports::type, \
@@ -709,9 +761,6 @@ public: \
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); \
} \
virtual PyObject *getattr(const char *name); \
virtual int setattr(const char *name, PyObject *val); \
@@ -740,5 +789,4 @@ PyXPCOM_ATTR_INTERFACE_DECLARE(Py_nsIClassInfo, nsIClassInfo, PyMethods_IClassIn
PyXPCOM_ATTR_INTERFACE_DECLARE(Py_nsIVariant, nsIVariant, PyMethods_IVariant)
// deprecated, but retained for backward compatibility:
PyXPCOM_INTERFACE_DECLARE(Py_nsIComponentManagerObsolete, nsIComponentManagerObsolete, PyMethods_IComponentManagerObsolete)
#endif // __PYXPCOM_H__

View File

@@ -49,29 +49,6 @@
//
// (c) 2000, ActiveState corp.
#include <Python.h>
#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 "nsIAllocator.h"
#include "nsIWeakReference.h"
#include "nsIInterfaceInfoManager.h"
#include "nsIClassInfo.h"
#include "nsIComponentManager.h"
#include "nsIComponentManagerObsolete.h"
#include "nsIServiceManager.h"
#include "nsIInputStream.h"
#include "nsIVariant.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

View File

@@ -152,7 +152,7 @@ PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *c)
v = PyString_FromStringAndSize(&c->value.ch, 1);
break;
case TD_WCHAR:
v = PyUnicode_FromPRUnichar((PRUnichar *)&c->value.wch, 1);
v = PyObject_FromNSString((PRUnichar *)&c->value.wch, 1);
break;
// TD_VOID = 13,
case TD_PNSIID:
@@ -163,7 +163,7 @@ PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *c)
v = PyString_FromString(c->value.str);
break;
case TD_PWSTRING:
v = PyUnicode_FromPRUnichar((PRUnichar *)c->value.wstr, nsCRT::strlen((PRUnichar *)c->value.wstr));
v = PyObject_FromNSString((PRUnichar *)c->value.wstr, nsCRT::strlen((PRUnichar *)c->value.wstr));
break;
// TD_INTERFACE_TYPE = 18,
// TD_INTERFACE_IS_TYPE = 19,

View File

@@ -69,10 +69,10 @@ static PyTypeObject PyInterfaceType_Type = {
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_xxx1*/
0, /*tp_xxx2*/
0, /*tp_xxx3*/
0, /*tp_xxx4*/
0, /* tp_getattro */
0, /*tp_setattro */
0, /* tp_as_buffer */
0, /* tp_flags */
"Define the behavior of a PythonCOM Interface type.",
};
@@ -149,7 +149,8 @@ PyXPCOM_TypeObject::Py_repr(PyObject *self)
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);
sprintf(buf, "<XPCOM object (%s) at 0x%p/0x%p>",
iid_repr, (void *)self, (void *)pis->m_obj.get());
nsMemory::Free(iid_repr);
return PyString_FromString(buf);
}
@@ -199,9 +200,24 @@ PyXPCOM_TypeObject::PyXPCOM_TypeObject( const char *name, PyXPCOM_TypeObject *pB
0, /* tp_as_number*/
0, /* tp_as_sequence */
0, /* tp_as_mapping */
Py_hash, /* tp_hash */
Py_hash, /* tp_hash */
0, /* tp_call */
Py_str, /* tp_str */
0, /* tp_getattro */
0, /*tp_setattro */
0, /* tp_as_buffer */
0, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
};
*((PyTypeObject *)this) = type_template;

View File

@@ -72,6 +72,9 @@ IsNullDOMString( const nsACString& aString )
return PR_FALSE;
}
#define PyUnicode_FromPRUnichar(src, size) \
PyUnicode_DecodeUTF16((char*)(src),sizeof(PRUnichar)*(size),NULL,NULL)
// Create a zero-terminated PRUnichar buffer from a Python unicode.
// On success, returns 0. On failure, returns -1 and sets an exception.
// dest_out must not be null. size_out may be null.
@@ -104,7 +107,7 @@ PyUnicode_AsPRUnichar(PyObject *obj, PRUnichar **dest_out, PRUint32 *size_out)
return 0;
}
PyObject *PyObject_FromNSString( const nsACString &s, PRBool bAssumeUTF8 = PR_FALSE )
PyObject *PyObject_FromNSString( const nsACString &s, PRBool bAssumeUTF8 /*= PR_FALSE */)
{
PyObject *ret;
if (IsNullDOMString(s)) {
@@ -134,12 +137,51 @@ PyObject *PyObject_FromNSString( const nsAString &s )
ret = Py_None;
Py_INCREF(Py_None);
} else {
const nsPromiseFlatString& temp = PromiseFlatString(s);
ret = PyUnicode_FromPRUnichar(temp.get(), temp.Length());
const nsPromiseFlatString& temp = PromiseFlatString(s);
ret = PyUnicode_FromPRUnichar(temp.get(), temp.Length());
}
return ret;
}
PyObject *PyObject_FromNSString( const PRUnichar *s,
PRUint32 len /* = (PRUint32)-1*/)
{
return PyUnicode_FromPRUnichar(s,
len==((PRUint32)-1)? nsCRT::strlen(s) : len);
}
PRBool PyObject_AsNSString( PyObject *val, nsAString &aStr)
{
if (val == Py_None) {
aStr.Truncate();
return NS_OK;
}
PyObject *val_use = NULL;
PRBool ok = PR_TRUE;
if (!PyString_Check(val) && !PyUnicode_Check(val)) {
PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
ok = PR_FALSE;
}
if (ok && (val_use = PyUnicode_FromObject(val))==NULL)
ok = PR_FALSE;
if (ok) {
if (PyUnicode_GET_SIZE(val_use) == 0) {
aStr.Truncate();
}
else {
PRUint32 nch;
PRUnichar *tempo;
// can we do this without the copy?
if (PyUnicode_AsPRUnichar(val_use, &tempo, &nch) < 0)
return PR_FALSE;
aStr.Assign(tempo, nch);
nsMemory::Free(tempo);
}
}
Py_XDECREF(val_use);
return ok;
}
// Array utilities
static PRUint32 GetArrayElementSize( PRUint8 t)
{
@@ -247,7 +289,8 @@ void FreeSingleArray(void *array_ptr, PRUint32 sequence_size, PRUint8 array_type
#define BREAK_FALSE {rc=PR_FALSE;break;}
PRBool FillSingleArray(void *array_ptr, PyObject *sequence_ob, PRUint32 sequence_size, PRUint32 array_element_size, PRUint8 array_type)
PRBool FillSingleArray(void *array_ptr, PyObject *sequence_ob, PRUint32 sequence_size,
PRUint32 array_element_size, PRUint8 array_type, nsIID *pIID)
{
PRUint8 *pthis = (PRUint8 *)array_ptr;
NS_ABORT_IF_FALSE(pthis, "Don't have a valid array to fill!");
@@ -441,7 +484,8 @@ PRBool FillSingleArray(void *array_ptr, PyObject *sequence_ob, PRUint32 sequence
return rc;
}
PyObject *UnpackSingleArray(void *array_ptr, PRUint32 sequence_size, PRUint8 array_type, nsIID *iid)
static PyObject *UnpackSingleArray(Py_nsISupports *parent, void *array_ptr,
PRUint32 sequence_size, PRUint8 array_type, nsIID *iid)
{
if (array_ptr==NULL) {
Py_INCREF(Py_None);
@@ -514,7 +558,17 @@ PyObject *UnpackSingleArray(void *array_ptr, PRUint32 sequence_size, PRUint8 arr
case nsXPTType::T_INTERFACE_IS:
case nsXPTType::T_INTERFACE: {
nsISupports **pp = (nsISupports **)pthis;
val = Py_nsISupports::PyObjectFromInterface(*pp, iid ? *iid : NS_GET_IID(nsISupports), PR_TRUE);
// If we have an owning parent, let it create
// the object for us.
if (iid && iid->Equals(NS_GET_IID(nsIVariant)))
val = PyObject_FromVariant(parent, (nsIVariant *)*pp);
else if (parent)
val = parent->MakeInterfaceResult(*pp, iid ? *iid : NS_GET_IID(nsISupports));
else
val = Py_nsISupports::PyObjectFromInterface(
*pp,
iid ? *iid : NS_GET_IID(nsISupports),
PR_TRUE);
break;
}
default: {
@@ -592,14 +646,11 @@ static PRUint16 BestVariantTypeForPyObject( PyObject *ob, BVFTResult *pdata = NU
return (PRUint16)-1;
}
nsIVariant *PyObject_AsVariant( PyObject *ob)
nsresult PyObject_AsVariant( PyObject *ob, nsIVariant **aRet)
{
nsresult nr = NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIWritableVariant> v = do_CreateInstance("@mozilla.org/variant;1", &nr);
if (NS_FAILED(nr)) {
PyXPCOM_BuildPyException(nr);
return NULL;
}
nsresult nr = NS_OK;
nsCOMPtr<nsIWritableVariant> v = do_CreateInstance("@mozilla.org/variant;1", &nr);
NS_ENSURE_SUCCESS(nr, nr);
// *sigh* - I tried the abstract API (PyNumber_Check, etc)
// but our COM instances too often qualify.
BVFTResult cvt_result;
@@ -628,6 +679,7 @@ nsIVariant *PyObject_AsVariant( PyObject *ob)
PRUint32 nch;
PRUnichar *p;
if (PyUnicode_AsPRUnichar(ob, &p, &nch) < 0) {
PyXPCOM_LogWarning("Failed to convert object to unicode", ob->ob_type->tp_name);
nr = NS_ERROR_UNEXPECTED;
break;
}
@@ -665,12 +717,11 @@ nsIVariant *PyObject_AsVariant( PyObject *ob)
int cb_buffer_pointer = seq_length * element_size;
void *buffer_pointer;
if ((buffer_pointer = (void *)nsMemory::Alloc(cb_buffer_pointer)) == nsnull) {
PyErr_NoMemory();
nr = NS_ERROR_UNEXPECTED;
nr = NS_ERROR_OUT_OF_MEMORY;
break;
}
memset(buffer_pointer, 0, cb_buffer_pointer);
if (FillSingleArray(buffer_pointer, ob, seq_length, element_size, array_type)) {
if (FillSingleArray(buffer_pointer, ob, seq_length, element_size, array_type, nsnull)) {
nr = v->SetAsArray(array_type, &NS_GET_IID(nsISupports), seq_length, buffer_pointer);
FreeSingleArray(buffer_pointer, seq_length, array_type);
} else
@@ -679,22 +730,22 @@ nsIVariant *PyObject_AsVariant( PyObject *ob)
break;
}
case nsIDataType::VTYPE_EMPTY:
v->SetAsEmpty();
nr = v->SetAsEmpty();
break;
case nsIDataType::VTYPE_EMPTY_ARRAY:
v->SetAsEmptyArray();
nr = v->SetAsEmptyArray();
break;
case (PRUint16)-1:
PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an nsIVariant", ob->ob_type->tp_name);
return NULL;
PyXPCOM_LogWarning("Objects of type '%s' can not be converted to an nsIVariant", ob->ob_type->tp_name);
nr = NS_ERROR_UNEXPECTED;
default:
NS_ABORT_IF_FALSE(0, "BestVariantTypeForPyObject() returned a variant type not handled here!");
PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an nsIVariant", ob->ob_type->tp_name);
return NULL;
PyXPCOM_LogWarning("Objects of type '%s' can not be converted to an nsIVariant", ob->ob_type->tp_name);
nr = NS_ERROR_UNEXPECTED;
}
nsIVariant *ret;
v->QueryInterface(NS_GET_IID(nsIVariant), (void **)&ret);
return ret;
if (NS_FAILED(nr))
return nr;
return v->QueryInterface(NS_GET_IID(nsIVariant), (void **)aRet);
}
static PyObject *MyBool_FromBool(PRBool v)
@@ -703,10 +754,6 @@ static PyObject *MyBool_FromBool(PRBool v)
Py_INCREF(ret);
return ret;
}
static PyObject *MyObject_FromInterface(nsISupports *p)
{
return Py_nsISupports::PyObjectFromInterface(p, NS_GET_IID(nsISupports), PR_FALSE);
}
#define GET_FROM_V(Type, FuncGet, FuncConvert) { \
Type t; \
@@ -715,7 +762,7 @@ static PyObject *MyObject_FromInterface(nsISupports *p)
break; \
}
PyObject *PyObject_FromVariantArray( nsIVariant *v)
PyObject *PyObject_FromVariantArray( Py_nsISupports *parent, nsIVariant *v)
{
nsresult nr;
NS_PRECONDITION(v, "NULL variant!");
@@ -732,13 +779,13 @@ PyObject *PyObject_FromVariantArray( nsIVariant *v)
PRUint32 count;
nr = v->GetAsArray(&type, &iid, &count, &p);
if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr);
PyObject *ret = UnpackSingleArray(p, count, (PRUint8)type, &iid);
PyObject *ret = UnpackSingleArray(parent, p, count, (PRUint8)type, &iid);
FreeSingleArray(p, count, (PRUint8)type);
nsMemory::Free(p);
return ret;
}
PyObject *PyObject_FromVariant( nsIVariant *v)
PyObject *PyObject_FromVariant( Py_nsISupports *parent, nsIVariant *v)
{
if (!v) {
Py_INCREF(Py_None);
@@ -757,7 +804,7 @@ PyObject *PyObject_FromVariant( nsIVariant *v)
Py_INCREF(Py_None);
break;
case nsIDataType::VTYPE_ARRAY:
ret = PyObject_FromVariantArray(v);
ret = PyObject_FromVariantArray(parent, v);
break;
case nsIDataType::VTYPE_INT8:
case nsIDataType::VTYPE_INT16:
@@ -799,13 +846,23 @@ PyObject *PyObject_FromVariant( nsIVariant *v)
}
case nsIDataType::VTYPE_ID:
GET_FROM_V(nsIID, v->GetAsID, Py_nsIID::PyObjectFromIID);
case nsIDataType::VTYPE_INTERFACE:
GET_FROM_V(nsISupports *, v->GetAsISupports, MyObject_FromInterface);
case nsIDataType::VTYPE_INTERFACE: {
nsCOMPtr<nsISupports> p;
if (NS_FAILED(nr=v->GetAsISupports(getter_AddRefs(p)))) goto done;
if (parent)
ret = parent->MakeInterfaceResult(p, NS_GET_IID(nsISupports));
else
ret = Py_nsISupports::PyObjectFromInterface(
p, NS_GET_IID(nsISupports), PR_TRUE);
break;
}
case nsIDataType::VTYPE_INTERFACE_IS: {
nsISupports *p;
nsCOMPtr<nsISupports> p;
nsIID *iid;
if (NS_FAILED(nr=v->GetAsInterface(&iid, (void **)&p))) goto done;
ret = Py_nsISupports::PyObjectFromInterface(p, *iid, PR_FALSE);
if (NS_FAILED(nr=v->GetAsInterface(&iid, getter_AddRefs(p)))) goto done;
// If the variant itself holds a variant, we should
// probably unpack that too?
ret = parent->MakeInterfaceResult(p, *iid);
break;
// case nsIDataType::VTYPE_WCHAR_STR
// case nsIDataType::VTYPE_UTF8STRING
@@ -899,16 +956,20 @@ Helpers when CALLING interfaces.
**************************************************************************
*************************************************************************/
PyXPCOM_InterfaceVariantHelper::PyXPCOM_InterfaceVariantHelper()
PyXPCOM_InterfaceVariantHelper::PyXPCOM_InterfaceVariantHelper(Py_nsISupports *parent)
{
m_var_array=nsnull;
m_buffer_array=nsnull;
m_pyparams=nsnull;
m_num_array = 0;
// Parent should never die before we do, but let's not take the chance.
m_parent = parent;
Py_INCREF(parent);
}
PyXPCOM_InterfaceVariantHelper::~PyXPCOM_InterfaceVariantHelper()
{
Py_DECREF(m_parent);
Py_XDECREF(m_pyparams);
for (int i=0;i<m_num_array;i++) {
if (m_var_array) {
@@ -1217,35 +1278,17 @@ PRBool PyXPCOM_InterfaceVariantHelper::FillInVariant(const PythonTypeDescriptor
break;
case nsXPTType::T_ASTRING:
case nsXPTType::T_DOMSTRING: {
if (val==Py_None) {
ns_v.val.p = new nsString();
} else {
if (!PyString_Check(val) && !PyUnicode_Check(val)) {
PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
BREAK_FALSE;
}
if ((val_use = PyUnicode_FromObject(val))==NULL)
BREAK_FALSE;
// Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a unicode object!");
if (PyUnicode_GET_SIZE(val_use) == 0) {
ns_v.val.p = new nsString();
}
else {
PRUint32 nch;
PRUnichar *tempo;
if (PyUnicode_AsPRUnichar(val_use, &tempo, &nch) < 0)
BREAK_FALSE;
ns_v.val.p = new nsString(tempo, nch);
nsMemory::Free(tempo);
}
}
if (!ns_v.val.p) {
nsString *s = new nsString();
if (!s) {
PyErr_NoMemory();
BREAK_FALSE;
}
ns_v.val.p = s;
// We created it - flag as such for cleanup.
ns_v.flags |= nsXPTCVariant::VAL_IS_DOMSTR;
if (!PyObject_AsNSString(val, *s))
BREAK_FALSE;
break;
}
case nsXPTType::T_CSTRING:
@@ -1440,7 +1483,7 @@ PRBool PyXPCOM_InterfaceVariantHelper::FillInVariant(const PythonTypeDescriptor
cb_this_buffer_pointer = 1;
MAKE_VALUE_BUFFER(cb_this_buffer_pointer);
memset(this_buffer_pointer, 0, cb_this_buffer_pointer);
rc = FillSingleArray(this_buffer_pointer, val, seq_length, element_size, array_type&XPT_TDP_TAGMASK);
rc = FillSingleArray(this_buffer_pointer, val, seq_length, element_size, array_type&XPT_TDP_TAGMASK, nsnull);
if (!rc) break;
rc = SetSizeIs(value_index, PR_FALSE, seq_length);
if (!rc) break;
@@ -1658,9 +1701,12 @@ PyObject *PyXPCOM_InterfaceVariantHelper::MakeSinglePythonResult(int index)
if (!Py_nsIID::IIDFromPyObject(td.extra, &iid))
break;
nsISupports *iret = *((nsISupports **)ns_v.ptr);
// We _do_ add a reference here, as our cleanup code will
// remove this reference should we own it.
ret = Py_nsISupports::PyObjectFromInterfaceOrVariant(iret, iid, PR_TRUE);
// Our cleanup code manages iret reference ownership, and our
// new object takes its own.
if (iid.Equals(NS_GET_IID(nsIVariant)))
ret = PyObject_FromVariant(m_parent, (nsIVariant *)iret);
else
ret = m_parent->MakeInterfaceResult(iret, iid);
break;
}
case nsXPTType::T_INTERFACE_IS: {
@@ -1674,15 +1720,18 @@ PyObject *PyXPCOM_InterfaceVariantHelper::MakeSinglePythonResult(int index)
iid = NS_GET_IID(nsISupports);
else
iid = *piid;
} else
} else {
// This is a pretty serious problem, but not Python's fault!
// Just return an nsISupports and hope the caller does whatever
// QI they need before using it.
NS_ERROR("Failed to get the IID for T_INTERFACE_IS!");
iid = NS_GET_IID(nsISupports);
}
nsISupports *iret = *((nsISupports **)ns_v.ptr);
// We _do_ add a reference here, as our cleanup code will
// remove this reference should we own it.
ret = Py_nsISupports::PyObjectFromInterfaceOrVariant(iret, iid, PR_TRUE);
if (iid.Equals(NS_GET_IID(nsIVariant)))
ret = PyObject_FromVariant(m_parent, (nsIVariant *)iret);
else
ret = m_parent->MakeInterfaceResult(iret, iid);
break;
}
case nsXPTType::T_ARRAY: {
@@ -1696,7 +1745,7 @@ PyObject *PyXPCOM_InterfaceVariantHelper::MakeSinglePythonResult(int index)
}
PRUint8 array_type = (PRUint8)PyInt_AsLong(td.extra);
PRUint32 seq_size = GetSizeIs(index, PR_FALSE);
ret = UnpackSingleArray(* ((void **)ns_v.ptr), seq_size, array_type&XPT_TDP_TAGMASK, NULL);
ret = UnpackSingleArray(m_parent, * ((void **)ns_v.ptr), seq_size, array_type&XPT_TDP_TAGMASK, NULL);
break;
}
@@ -2032,17 +2081,20 @@ PyObject *PyXPCOM_GatewayVariantHelper::MakeSingleParam(int index, PythonTypeDes
case nsXPTType::T_ARRAY: {
void *t = DEREF_IN_OR_OUT(ns_v.val.p, void *);
if (t==NULL) {
ret = Py_None;
Py_INCREF(Py_None);
// JS may send us a NULL here occasionally - as the
// type is array, we silently convert this to a zero
// length list, a-la JS.
ret = PyList_New(0);
} else {
PRUint8 array_type;
nsresult ns = GetArrayType(index, &array_type);
nsIID *piid;
nsresult ns = GetArrayType(index, &array_type, &piid);
if (NS_FAILED(ns)) {
PyXPCOM_BuildPyException(ns);
break;
}
PRUint32 seq_size = GetSizeIs(index, PR_FALSE);
ret = UnpackSingleArray(t, seq_size, array_type&XPT_TDP_TAGMASK, NULL);
ret = UnpackSingleArray(NULL, t, seq_size, array_type&XPT_TDP_TAGMASK, piid);
}
break;
}
@@ -2081,7 +2133,7 @@ PyObject *PyXPCOM_GatewayVariantHelper::MakeSingleParam(int index, PythonTypeDes
return ret;
}
nsresult PyXPCOM_GatewayVariantHelper::GetArrayType(PRUint8 index, PRUint8 *ret)
nsresult PyXPCOM_GatewayVariantHelper::GetArrayType(PRUint8 index, PRUint8 *ret, nsIID **iid)
{
nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(
NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
@@ -2098,6 +2150,13 @@ nsresult PyXPCOM_GatewayVariantHelper::GetArrayType(PRUint8 index, PRUint8 *ret)
rc = ii->GetTypeForParam(m_method_index, &param_info, 1, &datumType);
if (NS_FAILED(rc))
return rc;
if (iid) {
*iid = (nsIID *)&NS_GET_IID(nsISupports);
if (XPT_TDP_TAG(datumType)==nsXPTType::T_INTERFACE ||
XPT_TDP_TAG(datumType)==nsXPTType::T_INTERFACE_IS ||
XPT_TDP_TAG(datumType)==nsXPTType::T_ARRAY)
ii->GetIIDForParam(m_method_index, &param_info, iid);
}
*ret = datumType.flags;
return NS_OK;
}
@@ -2253,29 +2312,8 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index
case nsXPTType::T_DOMSTRING: {
nsAString *ws = (nsAString *)ns_v.val.p;
NS_ABORT_IF_FALSE(ws->Length() == 0, "Why does this writable string already have chars??");
if (val == Py_None) {
(*ws) = (PRUnichar *)nsnull;
} else {
if (!PyString_Check(val) && !PyUnicode_Check(val)) {
PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
BREAK_FALSE;
}
val_use = PyUnicode_FromObject(val);
if (!val_use)
BREAK_FALSE;
NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didn't return a Unicode object!");
if (PyUnicode_GET_SIZE(val_use) == 0) {
ws->Assign((PRUnichar*)NULL, 0);
}
else {
PRUint32 nch;
PRUnichar *sz;
if (PyUnicode_AsPRUnichar(val_use, &sz, &nch) < 0)
BREAK_FALSE;
ws->Assign(sz, nch);
nsMemory::Free(sz);
}
}
if (!PyObject_AsNSString(val, *ws))
BREAK_FALSE;
break;
}
case nsXPTType::T_CSTRING: {
@@ -2389,8 +2427,6 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index
break;
}
case nsXPTType::T_INTERFACE_IS: {
// We do allow NULL here, even tho doing so will no-doubt crash some objects.
// (but there will certainly be objects out there that will allow NULL :-(
const nsIID *piid;
if (!GetIIDForINTERFACE_ID(pi->type.argnum, &piid))
BREAK_FALSE;
@@ -2521,7 +2557,8 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index
// If it is an existing array of the correct size, keep it.
PRUint32 sequence_size = 0;
PRUint8 array_type;
nsresult ns = GetArrayType(index, &array_type);
nsIID *piid;
nsresult ns = GetArrayType(index, &array_type, &piid);
if (NS_FAILED(ns))
return ns;
PRUint32 element_size = GetArrayElementSize(array_type);
@@ -2548,7 +2585,7 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index
bBackFill = pi->IsIn();
}
if (bBackFill)
rc = FillSingleArray(*(void **)ns_v.val.p, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK);
rc = FillSingleArray(*(void **)ns_v.val.p, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK, piid);
else {
// If it is an existing array, free it.
void **pp = (void **)ns_v.val.p;
@@ -2563,7 +2600,7 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index
if (nbytes==0) nbytes = 1; // avoid assertion about 0 bytes
*pp = (void *)nsMemory::Alloc(nbytes);
memset(*pp, 0, nbytes);
rc = FillSingleArray(*pp, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK);
rc = FillSingleArray(*pp, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK, piid);
if (!rc) break;
if (bCanSetSizeIs)
rc = SetSizeIs(index, PR_FALSE, sequence_size);

View File

@@ -47,6 +47,8 @@
#include "PyXPCOM_std.h"
#include <prthread.h>
#include "nsIThread.h"
#include "nsILocalFile.h"
#ifdef XP_WIN
#ifndef WIN32_LEAN_AND_MEAN
@@ -58,6 +60,17 @@
static PRInt32 g_cLockCount = 0;
static PRLock *g_lockMain = nsnull;
PYXPCOM_EXPORT PyObject *PyXPCOM_Error = NULL;
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_nsIInputStream, nsIInputStream, PyMethods_IInputStream)
PyXPCOM_INTERFACE_DEFINE(Py_nsIClassInfo, nsIClassInfo, PyMethods_IClassInfo)
PyXPCOM_INTERFACE_DEFINE(Py_nsIVariant, nsIVariant, PyMethods_IVariant)
#ifndef PYXPCOM_USE_PYGILSTATE
////////////////////////////////////////////////////////////
@@ -245,3 +258,86 @@ struct DllInitializer {
pyxpcom_destruct();
}
} dll_initializer;
////////////////////////////////////////////////////////////
// Other helpers/global functions.
//
PRBool PyXPCOM_Globals_Ensure()
{
PRBool rc = PR_TRUE;
#ifndef PYXPCOM_USE_PYGILSTATE
PyXPCOM_InterpreterState_Ensure();
#endif
// 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.
#ifdef XP_WIN
// On Windows, we need to locate the Mozilla bin
// directory. This by using locating a Moz DLL we depend
// on, and assume it lives in that bin dir. Different
// moz build types (eg, xulrunner, suite) package
// XPCOM itself differently - but all appear to require
// nspr4.dll - so this is what we use.
char landmark[MAX_PATH+1];
HMODULE hmod = GetModuleHandle("nspr4.dll");
if (hmod==NULL) {
PyErr_SetString(PyExc_RuntimeError, "We dont appear to be linked against nspr4.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_ConvertASCIItoUCS2 strLandmark(landmark);
NS_NewLocalFile(strLandmark, PR_FALSE, getter_AddRefs(ns_bin_dir));
nsresult rv = NS_InitXPCOM2(nsnull, ns_bin_dir, nsnull);
#else
// Elsewhere, Mozilla can find it itself (we hope!)
nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
#endif // XP_WIN
if (NS_FAILED(rv)) {
PyErr_SetString(PyExc_RuntimeError, "The XPCOM subsystem could not be initialized");
return PR_FALSE;
}
}
// Even if xpcom was already init, we want to flag it as init!
bHaveInitXPCOM = PR_TRUE;
// Register our custom interfaces.
Py_nsISupports::InitType();
Py_nsIComponentManager::InitType();
Py_nsIInterfaceInfoManager::InitType();
Py_nsIEnumerator::InitType();
Py_nsISimpleEnumerator::InitType();
Py_nsIInterfaceInfo::InitType();
Py_nsIInputStream::InitType();
Py_nsIClassInfo::InitType();
Py_nsIVariant::InitType();
}
return rc;
}

View File

@@ -46,14 +46,22 @@ include $(DEPTH)/config/autoconf.mk
LIBRARY_NAME = pyloader
IS_COMPONENT = 1
REQUIRES = xpcom string xpcom_obsolete $(NULL)
REQUIRES = pyxpcom xpcom string xpcom_obsolete $(NULL)
MOZILLA_INTERNAL_API = 1
FORCE_SHARED_LIB = 1
FORCE_USE_PIC = 1
LOCAL_INCLUDES = $(PYTHON_INCLUDES)
EXTRA_LIBS += $(PYTHON_LIBS)
ifeq ($(OS_ARCH), WINNT)
EXTRA_LIBS += $(DIST)/lib/pyxpcom.lib
else
EXTRA_LIBS += -lpyxpcom
endif
CPPSRCS = \
pyloader.cpp \
$(NULL)

View File

@@ -41,26 +41,13 @@
//
// 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.
// pyxpcom core library and transfers control to that.
#include <Python.h>
#include <PyXPCOM.h>
#ifdef HAVE_LONG_LONG
#undef HAVE_LONG_LONG
#endif
#include "nsISupports.h"
#include "nsIModule.h"
#include "nsDirectoryServiceDefs.h"
#include "nsILocalFile.h"
#include "nsString.h"
#include "nsXPIDLString.h"
#include "nsString.h"
#include "stdlib.h"
#include "stdarg.h"
#include "nsReadableUtils.h"
#include "nsCRT.h"
#include "nspr.h" // PR_fprintf
#if (PY_VERSION_HEX >= 0x02030000)
@@ -86,9 +73,6 @@ typedef nsresult (*pfnPyXPCOM_NSGetModule)(nsIComponentManager *servMgr,
nsIModule** result);
pfnPyXPCOM_NSGetModule pfnEntryPoint = nsnull;
static void LogError(const char *fmt, ...);
static void LogDebug(const char *fmt, ...);
@@ -133,6 +117,63 @@ void AddStandardPaths()
}
}
////////////////////////////////////////////////////////////
// This is the main entry point that delegates into Python
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();
#ifndef PYXPCOM_USE_PYGILSTATE
PyXPCOM_InterpreterState_Ensure();
#endif
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));
if (obServMgr==NULL) goto done;
obLocation = Py_nsISupports::PyObjectFromInterface(location, NS_GET_IID(nsIFile));
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;
}
extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
nsIFile* location,
nsIModule** result)
@@ -152,7 +193,6 @@ extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
#ifndef NS_DEBUG
Py_OptimizeFlag = 1;
#endif // NS_DEBUG
AddStandardPaths();
PyEval_InitThreads();
NS_TIMELINE_STOP_TIMER("PyXPCOM: Python initializing");
NS_TIMELINE_MARK_TIMER("PyXPCOM: Python initializing");
@@ -177,25 +217,6 @@ extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
#else
PyGILState_STATE state = PyGILState_Ensure();
#endif // PYXPCOM_USE_PYGILSTATE
if (pfnEntryPoint == nsnull) {
PyObject *mod = PyImport_ImportModule("xpcom._xpcom");
if (mod==NULL) {
LogError("Could not import the Python XPCOM extension\n");
return NS_ERROR_FAILURE;
}
PyObject *obpfn = PyObject_GetAttrString(mod, "_NSGetModule_FuncPtr");
void *pfn = NULL;
if (obpfn) {
NS_ABORT_IF_FALSE(PyLong_Check(obpfn)||PyInt_Check(obpfn), "xpcom._NSGetModule_FuncPtr is not a long!");
pfn = PyLong_AsVoidPtr(obpfn);
}
pfnEntryPoint = (pfnPyXPCOM_NSGetModule)pfn;
}
if (pfnEntryPoint==NULL) {
LogError("Could not load main Python entry point\n");
return NS_ERROR_FAILURE;
}
#ifdef MOZ_TIMELINE
// If the timeline service is installed, see if we can install our hooks.
if (NULL==PyImport_ImportModule("timeline_hook")) {
@@ -204,6 +225,10 @@ extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
PyErr_Clear(); // but don't care if we can't.
}
#endif
// Add the standard paths always - we may not have been the first to
// init Python.
AddStandardPaths();
#ifndef PYXPCOM_USE_PYGILSTATE
// Abandon the thread-lock, as the first thing Python does
// is re-establish the lock (the Python thread-state story SUCKS!!!)
@@ -226,7 +251,7 @@ extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
NS_TIMELINE_STOP_TIMER("PyXPCOM: Python threadstate setup");
NS_TIMELINE_MARK_TIMER("PyXPCOM: Python threadstate setup");
NS_TIMELINE_START_TIMER("PyXPCOM: PyXPCOM NSGetModule entry point");
nsresult rc = (*pfnEntryPoint)(servMgr, location, result);
nsresult rc = PyXPCOM_NSGetModule(servMgr, location, result);
NS_TIMELINE_STOP_TIMER("PyXPCOM: PyXPCOM NSGetModule entry point");
NS_TIMELINE_MARK_TIMER("PyXPCOM: PyXPCOM NSGetModule entry point");
return rc;

View File

@@ -0,0 +1,94 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is mozilla.org
# Portions created by the Initial Developer are Copyright (C) 2002
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Mark Hammond <mhammond@skippinet.com.au> (original author)
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
# The xpcom._xpcom module
DEPTH=../../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
pyexecdir = @libdir@/python$(PYTHON_VER_DOTTED)/site-packages
include $(DEPTH)/config/autoconf.mk
LIBRARY_NAME = _xpcom$(PYTHON_DEBUG_SUFFIX)
REQUIRES = pyxpcom xpcom string $(NULL)
MOZILLA_INTERNAL_API = 1
FORCE_SHARED_LIB = 1
FORCE_USE_PIC = 1
DLL_SUFFIX=$(PYTHON_DLL_SUFFIX)
LOCAL_INCLUDES = $(PYTHON_INCLUDES)
EXTRA_LIBS += $(PYTHON_LIBS)
ifeq ($(OS_ARCH), WINNT)
EXTRA_LIBS += $(DIST)/lib/pyxpcom.lib
else
EXTRA_LIBS += -lpyxpcom
endif
CPPSRCS= \
_xpcom.cpp \
$(NULL)
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/config/rules.mk
EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
IMPORT_LIBRARY := $(SHARED_LIBRARY:.pyd=.lib)
# Install into our Python directory
# default build installs into bin and lib - remove them
libs::
ifeq ($(OS_ARCH),WINNT)
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(DIST)/bin/python/xpcom
else
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(DIST)/bin/python/xpcom
mv $(DIST)/bin/python/xpcom/$(SHARED_LIBRARY) $(DIST)/bin/python/xpcom/_xpcom.so
endif
rm -f $(DIST)/bin/$(SHARED_LIBRARY)
rm -f $(DIST)/lib/$(IMPORT_LIBRARY)
install::
ifneq ($(OS_ARCH),WINNT)
$(SYSINSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(DISTDIR)$(pyexecdir)/xpcom
mv $(DISTDIR)$(pyexecdir)/xpcom/$(SHARED_LIBRARY) $(DISTDIR)$(pyexecdir)/xpcom/_xpcom$(PYTHON_DLL_SUFFIX)
endif
clobber::
rm -f *.ilk *.pdb

View File

@@ -45,14 +45,13 @@
//
// (c) 2000, ActiveState corp.
#include "PyXPCOM_std.h"
#include "nsIThread.h"
#include "PyXPCOM.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsIModule.h"
#include "nsIFile.h"
#include "nsILocalFile.h"
#include "nsIComponentRegistrar.h"
#include "nsIConsoleService.h"
#include "nspr.h" // PR_fprintf
#ifdef XP_WIN
#ifndef WIN32_LEAN_AND_MEAN
@@ -64,85 +63,12 @@
#include "nsIEventQueue.h"
#include "nsIProxyObjectManager.h"
PYXPCOM_EXPORT PyObject *PyXPCOM_Error = NULL;
extern PRInt32 _PyXPCOM_GetGatewayCount(void);
extern PRInt32 _PyXPCOM_GetInterfaceCount(void);
extern void AddDefaultGateway(PyObject *instance, nsISupports *gateway);
#define LOADER_LINKS_WITH_PYTHON
#ifndef PYXPCOM_USE_PYGILSTATE
extern void PyXPCOM_InterpreterState_Ensure();
extern PYXPCOM_EXPORT void PyXPCOM_InterpreterState_Ensure();
#endif
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_nsIInputStream, nsIInputStream, PyMethods_IInputStream)
PyXPCOM_INTERFACE_DEFINE(Py_nsIClassInfo, nsIClassInfo, PyMethods_IClassInfo)
PyXPCOM_INTERFACE_DEFINE(Py_nsIVariant, nsIVariant, PyMethods_IVariant)
////////////////////////////////////////////////////////////
// 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();
#ifndef PYXPCOM_USE_PYGILSTATE
PyXPCOM_InterpreterState_Ensure();
#endif
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;
}
// "boot-strap" methods - interfaces we need to get the base
// interface support!
@@ -151,15 +77,33 @@ PyXPCOMMethod_GetComponentManager(PyObject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
nsIComponentManager* cm;
nsCOMPtr<nsIComponentManager> cm;
nsresult rv;
Py_BEGIN_ALLOW_THREADS;
rv = NS_GetComponentManager(&cm);
rv = NS_GetComponentManager(getter_AddRefs(cm));
Py_END_ALLOW_THREADS;
if ( NS_FAILED(rv) )
return PyXPCOM_BuildPyException(rv);
return Py_nsISupports::PyObjectFromInterface(cm, NS_GET_IID(nsIComponentManager), PR_FALSE, PR_FALSE);
return Py_nsISupports::PyObjectFromInterface(cm, NS_GET_IID(nsIComponentManager), PR_FALSE);
}
// No xpcom callable way to get at the registrar, even though the interface
// is scriptable.
static PyObject *
PyXPCOMMethod_GetComponentRegistrar(PyObject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
nsCOMPtr<nsIComponentRegistrar> cm;
nsresult rv;
Py_BEGIN_ALLOW_THREADS;
rv = NS_GetComponentRegistrar(getter_AddRefs(cm));
Py_END_ALLOW_THREADS;
if ( NS_FAILED(rv) )
return PyXPCOM_BuildPyException(rv);
return Py_nsISupports::PyObjectFromInterface(cm, NS_GET_IID(nsISupports), PR_FALSE);
}
static PyObject *
@@ -167,16 +111,16 @@ PyXPCOMMethod_GetServiceManager(PyObject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
nsIServiceManager* sm;
nsCOMPtr<nsIServiceManager> sm;
nsresult rv;
Py_BEGIN_ALLOW_THREADS;
rv = NS_GetServiceManager(&sm);
rv = NS_GetServiceManager(getter_AddRefs(sm));
Py_END_ALLOW_THREADS;
if ( NS_FAILED(rv) )
return PyXPCOM_BuildPyException(rv);
// Return a type based on the IID.
return Py_nsISupports::PyObjectFromInterface(sm, NS_GET_IID(nsIServiceManager), PR_FALSE);
return Py_nsISupports::PyObjectFromInterface(sm, NS_GET_IID(nsIServiceManager));
}
static PyObject *
@@ -192,7 +136,7 @@ PyXPCOMMethod_XPTI_GetInterfaceInfoManager(PyObject *self, PyObject *args)
/* 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_TRUE, PR_FALSE);
return Py_nsISupports::PyObjectFromInterface(im, NS_GET_IID(nsIInterfaceInfoManager), PR_FALSE);
}
static PyObject *
@@ -209,6 +153,11 @@ PyXPCOMMethod_XPTC_InvokeByIndex(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "OiO", &obIS, &index, &obParams))
return NULL;
if (!Py_nsISupports::Check(obIS)) {
return PyErr_Format(PyExc_TypeError,
"First param must be a native nsISupports wrapper (got %s)",
obIS->ob_type->tp_name);
}
// 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,
@@ -220,7 +169,7 @@ PyXPCOMMethod_XPTC_InvokeByIndex(PyObject *self, PyObject *args)
PR_FALSE))
return NULL;
PyXPCOM_InterfaceVariantHelper arg_helper;
PyXPCOM_InterfaceVariantHelper arg_helper((Py_nsISupports *)obIS);
if (!arg_helper.Init(obParams))
return NULL;
@@ -249,8 +198,8 @@ PyXPCOMMethod_WrapObject(PyObject *self, PyObject *args)
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
return NULL;
nsISupports *ret = NULL;
nsresult r = PyXPCOM_XPTStub::CreateNew(ob, iid, (void **)&ret);
nsCOMPtr<nsISupports> ret;
nsresult r = PyXPCOM_XPTStub::CreateNew(ob, iid, getter_AddRefs(ret));
if ( NS_FAILED(r) )
return PyXPCOM_BuildPyException(r);
@@ -259,7 +208,7 @@ PyXPCOMMethod_WrapObject(PyObject *self, PyObject *args)
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, bWrapClient);
return Py_nsISupports::PyObjectFromInterface(ret, iid, bWrapClient);
}
static PyObject *
@@ -327,8 +276,8 @@ PyXPCOMMethod_NS_ShutdownXPCOM(PyObject *self, PyObject *args)
nr = NS_ShutdownXPCOM(nsnull);
Py_END_ALLOW_THREADS;
// Don't raise an exception - as we are probably shutting down
// and don't really care - just return the status
// Dont raise an exception - as we are probably shutting down
// and dont really case - just return the status
return PyInt_FromLong(nr);
}
@@ -360,7 +309,7 @@ PyXPCOMMethod_GetProxyForObject(PyObject *self, PyObject *args)
}
nsresult rv_proxy;
nsISupports *presult = nsnull;
nsCOMPtr<nsISupports> presult;
Py_BEGIN_ALLOW_THREADS;
nsCOMPtr<nsIProxyObjectManager> proxyMgr =
do_GetService(kProxyObjectManagerCID, &rv_proxy);
@@ -370,7 +319,7 @@ PyXPCOMMethod_GetProxyForObject(PyObject *self, PyObject *args)
iid,
pob,
flags,
(void **)&presult);
getter_AddRefs(presult));
}
if (pQueueRelease)
pQueueRelease->Release();
@@ -378,24 +327,69 @@ PyXPCOMMethod_GetProxyForObject(PyObject *self, PyObject *args)
PyObject *result;
if (NS_SUCCEEDED(rv_proxy) ) {
result = Py_nsISupports::PyObjectFromInterface(presult, iid, PR_FALSE);
result = Py_nsISupports::PyObjectFromInterface(presult, iid);
} else {
result = PyXPCOM_BuildPyException(rv_proxy);
}
return result;
}
static PyObject *
PyXPCOMMethod_MakeVariant(PyObject *self, PyObject *args)
{
PyObject *ob;
if (!PyArg_ParseTuple(args, "O:MakeVariant", &ob))
return NULL;
nsCOMPtr<nsIVariant> pVar;
nsresult nr = PyObject_AsVariant(ob, getter_AddRefs(pVar));
if (NS_FAILED(nr))
return PyXPCOM_BuildPyException(nr);
if (pVar == nsnull) {
NS_ERROR("PyObject_AsVariant worked but returned a NULL ptr!");
return PyXPCOM_BuildPyException(NS_ERROR_UNEXPECTED);
}
return Py_nsISupports::PyObjectFromInterface(pVar, NS_GET_IID(nsIVariant));
}
static PyObject *
PyXPCOMMethod_GetVariantValue(PyObject *self, PyObject *args)
{
PyObject *ob, *obParent = NULL;
if (!PyArg_ParseTuple(args, "O|O:GetVariantValue", &ob, &obParent))
return NULL;
nsCOMPtr<nsIVariant> var;
if (!Py_nsISupports::InterfaceFromPyObject(ob,
NS_GET_IID(nsISupports),
getter_AddRefs(var),
PR_FALSE))
return PyErr_Format(PyExc_ValueError,
"Object is not an nsIVariant (got %s)",
ob->ob_type->tp_name);
Py_nsISupports *parent = nsnull;
if (obParent && obParent != Py_None) {
if (!Py_nsISupports::Check(obParent)) {
PyErr_SetString(PyExc_ValueError,
"Object not an nsISupports wrapper");
return NULL;
}
parent = (Py_nsISupports *)obParent;
}
return PyObject_FromVariant(parent, var);
}
PyObject *PyGetSpecialDirectory(PyObject *self, PyObject *args)
{
char *dirname;
if (!PyArg_ParseTuple(args, "s:GetSpecialDirectory", &dirname))
return NULL;
nsIFile *file = NULL;
nsresult r = NS_GetSpecialDirectory(dirname, &file);
nsCOMPtr<nsIFile> file;
nsresult r = NS_GetSpecialDirectory(dirname, getter_AddRefs(file));
if ( NS_FAILED(r) )
return PyXPCOM_BuildPyException(r);
// returned object swallows our reference.
return Py_nsISupports::PyObjectFromInterface(file, NS_GET_IID(nsIFile), PR_FALSE);
return Py_nsISupports::PyObjectFromInterface(file, NS_GET_IID(nsIFile));
}
PyObject *AllocateBuffer(PyObject *self, PyObject *args)
@@ -406,31 +400,38 @@ PyObject *AllocateBuffer(PyObject *self, PyObject *args)
return PyBuffer_New(bufSize);
}
PyObject *LogWarning(PyObject *self, PyObject *args)
// Writes a message to the console service. This could be done via pure
// Python code, but is useful when the logging code is actually the
// xpcom .py framework itself (ie, we don't want our logging framework to
// call back into the very code generating the log messages!
PyObject *LogConsoleMessage(PyObject *self, PyObject *args)
{
char *msg;
if (!PyArg_ParseTuple(args, "s", &msg))
return NULL;
PyXPCOM_LogWarning("%s", msg);
nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
if (consoleService)
consoleService->LogStringMessage(NS_ConvertASCIItoUCS2(msg).get());
else {
// This either means no such service, or in shutdown - hardly worth
// the warning, and not worth reporting an error to Python about - its
// log handler would just need to catch and ignore it.
// And as this is only called by this logging setup, any messages should
// still go to stderr or a logfile.
NS_WARNING("pyxpcom can't log console message.");
}
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);
extern PYXPCOM_EXPORT PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args);
static struct PyMethodDef xpcom_methods[]=
{
{"GetComponentManager", PyXPCOMMethod_GetComponentManager, 1},
{"GetComponentRegistrar", PyXPCOMMethod_GetComponentRegistrar, 1},
{"XPTI_GetInterfaceInfoManager", PyXPCOMMethod_XPTI_GetInterfaceInfoManager, 1},
{"XPTC_InvokeByIndex", PyXPCOMMethod_XPTC_InvokeByIndex, 1},
{"GetServiceManager", PyXPCOMMethod_GetServiceManager, 1},
@@ -445,83 +446,13 @@ static struct PyMethodDef xpcom_methods[]=
{"GetProxyForObject", PyXPCOMMethod_GetProxyForObject, 1},
{"GetSpecialDirectory", PyGetSpecialDirectory, 1},
{"AllocateBuffer", AllocateBuffer, 1},
{"LogWarning", LogWarning, 1},
{"LogError", LogError, 1},
{"LogConsoleMessage", LogConsoleMessage, 1, "Write a message to the xpcom console service"},
{"MakeVariant", PyXPCOMMethod_MakeVariant, 1},
{"GetVariantValue", PyXPCOMMethod_GetVariantValue, 1},
// These should no longer be used - just use the logging.getLogger('pyxpcom')...
{ NULL }
};
////////////////////////////////////////////////////////////
// Other helpers/global functions.
//
PRBool PyXPCOM_Globals_Ensure()
{
PRBool rc = PR_TRUE;
#ifndef PYXPCOM_USE_PYGILSTATE
PyXPCOM_InterpreterState_Ensure();
#endif
// 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.
#ifdef XP_WIN
// On Windows, we need to locate the Mozilla bin
// directory. This by using locating a Moz DLL we depend
// on, and assume it lives in that bin dir. Different
// moz build types (eg, xulrunner, suite) package
// XPCOM itself differently - but all appear to require
// nspr4.dll - so this is what we use.
char landmark[MAX_PATH+1];
HMODULE hmod = GetModuleHandle("nspr4.dll");
if (hmod==NULL) {
PyErr_SetString(PyExc_RuntimeError, "We dont appear to be linked against nspr4.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_ConvertASCIItoUCS2 strLandmark(landmark);
NS_NewLocalFile(strLandmark, PR_FALSE, getter_AddRefs(ns_bin_dir));
nsresult rv = NS_InitXPCOM2(nsnull, ns_bin_dir, nsnull);
#else
// Elsewhere, Mozilla can find it itself (we hope!)
nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
#endif // XP_WIN
if (NS_FAILED(rv)) {
PyErr_SetString(PyExc_RuntimeError, "The XPCOM subsystem could not be initialized");
return PR_FALSE;
}
}
// 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); \
@@ -562,16 +493,9 @@ init_xpcom() {
}
PyDict_SetItemString(dict, "IIDType", (PyObject *)&Py_nsIID::type);
// register our entry point.
PyObject *obFuncPtr = PyLong_FromVoidPtr((void *)&PyXPCOM_NSGetModule);
if (obFuncPtr)
PyDict_SetItemString(dict,
"_NSGetModule_FuncPtr",
obFuncPtr);
Py_XDECREF(obFuncPtr);
REGISTER_IID(nsISupports);
REGISTER_IID(nsISupportsCString);
REGISTER_IID(nsISupportsString);
REGISTER_IID(nsIModule);
REGISTER_IID(nsIFactory);
REGISTER_IID(nsIWeakReference);
@@ -579,20 +503,33 @@ init_xpcom() {
REGISTER_IID(nsIClassInfo);
REGISTER_IID(nsIServiceManager);
REGISTER_IID(nsIComponentRegistrar);
// Register our custom interfaces.
REGISTER_IID(nsIComponentManager);
REGISTER_IID(nsIInterfaceInfoManager);
REGISTER_IID(nsIEnumerator);
REGISTER_IID(nsISimpleEnumerator);
REGISTER_IID(nsIInterfaceInfo);
REGISTER_IID(nsIInputStream);
REGISTER_IID(nsIClassInfo);
REGISTER_IID(nsIVariant);
// for backward compatibility:
REGISTER_IID(nsIComponentManagerObsolete);
Py_nsISupports::InitType();
Py_nsIComponentManager::InitType(dict);
Py_nsIInterfaceInfoManager::InitType(dict);
Py_nsIEnumerator::InitType(dict);
Py_nsISimpleEnumerator::InitType(dict);
Py_nsIInterfaceInfo::InitType(dict);
Py_nsIInputStream::InitType(dict);
Py_nsIClassInfo::InitType(dict);
Py_nsIVariant::InitType(dict);
// No good reason not to expose this impl detail, and tests can use it
REGISTER_IID(nsIInternalPython);
// We have special support for proxies - may as well add their constants!
REGISTER_INT(PROXY_SYNC);
REGISTER_INT(PROXY_ASYNC);
REGISTER_INT(PROXY_ALWAYS);
// Build flags that may be useful.
PyObject *ob = PyBool_FromLong(
#ifdef NS_DEBUG
1
#else
0
#endif
);
PyDict_SetItemString(dict, "NS_DEBUG", ob);
Py_DECREF(ob);
}