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:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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, ¶m_info, &pnewii);
|
||||
nsCOMPtr<nsIInterfaceInfo> pnewii;
|
||||
nsresult n = pii->GetInfoForParam(mi, ¶m_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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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}
|
||||
};
|
||||
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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, ¶m_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, ¶m_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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
94
mozilla/extensions/python/xpcom/src/module/Makefile.in
Normal file
94
mozilla/extensions/python/xpcom/src/module/Makefile.in
Normal 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
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user