nsresult PyG_Base::HandleNativeGatewayError(const char *szMethodName) { nsresult rc = NS_OK; if (PyErr_Occurred()) { // The error handling - fairly involved, but worth it as // good error reporting is critical for users to know WTF // is going on - especially with TypeErrors etc in their // return values (ie, after the Python code has successfully // 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 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. PRBool bProcessMainError = PR_TRUE; // set to false if our exception handler does its thing! PyObject *exc_typ, *exc_val, *exc_tb; PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); PyObject *err_result = PyObject_CallMethod(m_pPyObject, (char*)"_GatewayException_", (char*)"z(OOO)", szMethodName, exc_typ ? exc_typ : Py_None, // should never be NULL, but defensive programming... exc_val ? exc_val : Py_None, // may well be NULL. exc_tb ? exc_tb : Py_None); // may well be NULL. if (err_result == NULL) { PyXPCOM_LogError("The exception handler _CallMethodException_ failed!\n"); } else if (err_result == Py_None) { // The exception handler has chosen not to do anything with // this error, so we still need to print it! ; } else if (PyInt_Check(err_result)) { // The exception handler has given us the nresult. rc = PyInt_AsLong(err_result); bProcessMainError = PR_FALSE; } else { // The exception handler succeeded, but returned other than // int or None. PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", err_result->ob_type->tp_name); } Py_XDECREF(err_result); PyErr_Restore(exc_typ, exc_val, exc_tb); if (bProcessMainError) { PyXPCOM_LogError("The function '%s' failed\n", szMethodName); rc = PyXPCOM_SetCOMErrorFromPyException(); } PyErr_Clear(); } return rc; }
// nsIArray impl NS_IMETHODIMP nsPyArgArray::GetLength(PRUint32 *aLength) { CEnterLeavePython _celp; int size = PySequence_Length(mObject); if (size==-1) { return PyXPCOM_SetCOMErrorFromPyException(); } *aLength = (PRUint32) size; return NS_OK; }
/* void queryElementAt (in unsigned long index, in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */ NS_IMETHODIMP nsPyArgArray::QueryElementAt(PRUint32 index, const nsIID & uuid, void * *result) { *result = nsnull; // for now let Python check index validity. Probably won't get the correct // hresult, but its not even clear what that is :) if (uuid.Equals(NS_GET_IID(nsIVariant)) || uuid.Equals(NS_GET_IID(nsISupports))) { CEnterLeavePython _celp; PyObject *sub = PySequence_GetItem(mObject, index); if (sub==NULL) { return PyXPCOM_SetCOMErrorFromPyException(); } nsresult rv = PyObject_AsVariant(sub, (nsIVariant **)result); Py_DECREF(sub); return rv; } NS_WARNING("nsPyArgArray only handles nsIVariant"); return NS_ERROR_NO_INTERFACE; }