⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qtlib.c

📁 这是关于RFC3261实现sip的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			return 0;		}		if ((sfunc = PyMethod_New(slot->meth.mfunc, self, slot->meth.mclass)) == NULL)		{			Py_XDECREF(sref);			return -1;		}		// Make sure we garbage collect the new method.		newmeth = sfunc;	}	else if (slot -> name != NULL)	{		char *mname = slot -> name + 1;		PyObject *self = (sref != NULL ? sref : slot->pyobj);		// See if any underlying C++ instance has gone.		if (self != NULL && sip_api_wrapper_check(self) && ((sipWrapper *)self)->u.cppPtr == NULL)		{			Py_XDECREF(sref);			return 0;		}		if ((sfunc = PyObject_GetAttrString(self, mname)) == NULL || !PyCFunction_Check(sfunc))		{			// Note that in earlier versions of SIP this error			// would be detected when the slot was connected.			PyErr_Format(PyExc_NameError,"Invalid slot %s",mname);			Py_XDECREF(sref);			return -1;		}		// Make sure we garbage collect the new method.		newmeth = sfunc;	}	else	{		sfunc = slot -> pyobj;		newmeth = NULL;	}	// We make repeated attempts to call a slot.  If we work out that it	// failed because of an immediate type error we try again with one less	// argument.  We keep going until we run out of arguments to drop.	// This emulates the Qt ability of the slot to accept fewer arguments	// than a signal provides.	sa = sigargs;        Py_INCREF(sa);	for (;;)	{		PyObject *nsa, *xtype, *xvalue, *xtb, *resobj;		if ((resobj = PyEval_CallObject(sfunc,sa)) != NULL)		{			Py_DECREF(resobj);			Py_XDECREF(newmeth);			Py_XDECREF(sref);			// Remove any previous exception. */			if (sa != sigargs)			{				Py_XDECREF(oxtype);				Py_XDECREF(oxvalue);				Py_XDECREF(oxtb);				PyErr_Clear();			}			Py_DECREF(sa);			return 0;		}		// Get the exception.		PyErr_Fetch(&xtype,&xvalue,&xtb);		// See if it is unacceptable.  An acceptable failure is a type		// error with no traceback - so long as we can still reduce the		// number of arguments and try again.		if (!PyErr_GivenExceptionMatches(xtype,PyExc_TypeError) ||		    xtb != NULL ||		    PyTuple_GET_SIZE(sa) == 0)		{			// If there is a traceback then we must have called the                        // slot and the exception was later on - so report the                        // exception as is.                        if (xtb != NULL)                        {                                if (sa != sigargs)                                {				        Py_XDECREF(oxtype);				        Py_XDECREF(oxvalue);				        Py_XDECREF(oxtb);                                }                                PyErr_Restore(xtype,xvalue,xtb);                        }			else if (sa == sigargs)				PyErr_Restore(xtype,xvalue,xtb);			else			{				// Discard the latest exception and restore the				// original one.				Py_XDECREF(xtype);				Py_XDECREF(xvalue);				Py_XDECREF(xtb);				PyErr_Restore(oxtype,oxvalue,oxtb);			}			break;		}		// If this is the first attempt, save the exception.		if (sa == sigargs)		{			oxtype = xtype;			oxvalue = xvalue;			oxtb = xtb;		}		else		{			Py_XDECREF(xtype);			Py_XDECREF(xvalue);			Py_XDECREF(xtb);		}		// Create the new argument tuple.		if ((nsa = PyTuple_GetSlice(sa,0,PyTuple_GET_SIZE(sa) - 1)) == NULL)		{			// Tidy up.			Py_XDECREF(oxtype);			Py_XDECREF(oxvalue);			Py_XDECREF(oxtb);			break;		}	        Py_DECREF(sa);		sa = nsa;	}	Py_XDECREF(newmeth);	Py_XDECREF(sref);        Py_DECREF(sa);	return -1;}// Send a signal to the slots (Qt or Python) in a Python list.static int emitToSlotList(sipPySigRx *rxlist,PyObject *sigargs){	int rc;	// Apply the arguments to each slot method.	rc = 0;	while (rxlist != NULL && rc >= 0)	{		sipPySigRx *next;		// We get the next in the list before calling the slot in case		// the list gets changed by the slot - usually because the slot		// disconnects itself.		next = rxlist -> next;		rc = sip_api_emit_to_slot(&rxlist -> rx, sigargs);		rxlist = next;	}	return rc;}// Add a slot to a transmitter's Python signal list.  The signal is a Python// signal, the slot may be either a Qt signal, a Qt slot, a Python signal or a// Python slot.static int addSlotToPySigList(sipWrapper *txSelf,const char *sig,			      PyObject *rxObj,const char *slot){	sipPySig *ps;	sipPySigRx *psrx;	// Create a new one if necessary.	if ((ps = findPySignal(txSelf,sig)) == NULL)	{		if ((ps = (sipPySig *)sip_api_malloc(sizeof (sipPySig))) == NULL)			return -1;		if ((ps -> name = sipStrdup(sig)) == NULL)		{			sip_api_free(ps);			return -1;		}		ps -> rxlist = NULL;		ps -> next = txSelf -> pySigList;		txSelf -> pySigList = ps;	}	// Create the new receiver.	if ((psrx = (sipPySigRx *)sip_api_malloc(sizeof (sipPySigRx))) == NULL)		return -1;	if (saveSlot(&psrx->rx, rxObj, slot) < 0)	{		sip_api_free(psrx);		return -1;	}	psrx -> next = ps -> rxlist;	ps -> rxlist = psrx;	return 0;}// Compare two slots to see if they are the same.static int isSameSlot(sipSlot *slot1,PyObject *rxobj2,const char *slot2){	// See if they are signals or Qt slots, ie. they have a name.	if (slot1 -> name != NULL)		return (slot2 != NULL &&			sipQtSupport->qt_same_name(slot1 -> name,slot2) &&			slot1 -> pyobj == rxobj2);	// Both must be Python slots.	if (slot2 != NULL)		return 0;	// See if they are Python methods.	if (slot1 -> pyobj == NULL)		return (PyMethod_Check(rxobj2) &&			slot1 -> meth.mfunc == PyMethod_GET_FUNCTION(rxobj2) &&			slot1 -> meth.mself == PyMethod_GET_SELF(rxobj2) &&			slot1 -> meth.mclass == PyMethod_GET_CLASS(rxobj2));	if (PyMethod_Check(rxobj2))		return 0;	// The objects must be the same.	return (slot1 -> pyobj == rxobj2);}// Convert a valid Python signal or slot to an existing universal slot.void *sipGetRx(sipWrapper *txSelf,const char *sigargs,PyObject *rxObj,	       const char *slot,const char **memberp){	if (slot != NULL)		if (isQtSlot(slot) || isQtSignal(slot))		{			void *rx;			*memberp = slot;			if ((rx = sip_api_get_cpp_ptr((sipWrapper *)rxObj, sipQObjectClass)) == NULL)				return NULL;			if (isQtSignal(slot))				rx = findSignal(rx, memberp);			return rx;		}	// The slot was either a Python callable or PyQt3 Python signal so	// there should be a universal slot.	return sipQtSupport->qt_find_slot(sipGetAddress(txSelf), sigargs, rxObj, slot, memberp);}// Convert a Python receiver (either a Python signal or slot or a Qt signal// or slot) to a Qt receiver.  It is only ever called when the signal is a// Qt signal.  Return NULL is there was an error.void *sip_api_convert_rx(sipWrapper *txSelf,const char *sig,PyObject *rxObj,			 const char *slot,const char **memberp){	if (slot == NULL)		return createUniversalSlot(txSelf, sig, rxObj, NULL, memberp);	if (isQtSlot(slot) || isQtSignal(slot))	{		void *rx;		*memberp = slot;		if ((rx = sip_api_get_cpp_ptr((sipWrapper *)rxObj, sipQObjectClass)) == NULL)			return NULL;		if (isQtSignal(slot))			rx = newSignal(rx, memberp);		return rx;	}	// The slot is a Python signal so we need a universal slot to catch it.	return createUniversalSlot(txSelf, sig, rxObj, slot, memberp);}// Connect a Qt signal or a Python signal to a Qt slot, a Qt signal, a Python// slot or a Python signal.  This is all possible combinations.PyObject *sip_api_connect_rx(PyObject *txObj,const char *sig,PyObject *rxObj,			     const char *slot, int type){	sipWrapper *txSelf = (sipWrapper *)txObj;	// Handle Qt signals.	if (isQtSignal(sig))	{		void *tx, *rx;		const char *member, *real_sig;		int res;		if ((tx = sip_api_get_cpp_ptr(txSelf, sipQObjectClass)) == NULL)			return NULL;		real_sig = sig;		if ((tx = newSignal(tx, &real_sig)) == NULL)			return NULL;		if ((rx = sip_api_convert_rx(txSelf, sig, rxObj, slot, &member)) == NULL)			return NULL;		Py_BEGIN_ALLOW_THREADS		res = sipQtSupport->qt_connect(tx, real_sig, rx, member, type);		Py_END_ALLOW_THREADS		return PyBool_FromLong(res);	}	// Handle Python signals.	if (addSlotToPySigList(txSelf, sig, rxObj, slot) < 0)		return NULL;	Py_INCREF(Py_True);	return Py_True;}// Disconnect a signal to a signal or a Qt slot.PyObject *sip_api_disconnect_rx(PyObject *txObj,const char *sig,				PyObject *rxObj,const char *slot){	sipWrapper *txSelf = (sipWrapper *)txObj;	// Handle Qt signals.	if (isQtSignal(sig))	{		void *tx, *rx;		const char *member;		PyObject *res;		if ((tx = sip_api_get_cpp_ptr(txSelf, sipQObjectClass)) == NULL)			return NULL;		if ((rx = sipGetRx(txSelf, sig, rxObj, slot, &member)) == NULL)		{			Py_INCREF(Py_False);			return Py_False;		}		res = PyBool_FromLong(sipQtSupport->qt_disconnect(tx, sig, rx, member));		// Delete it if it is a universal slot as this will be it's		// only connection.  If the slot is actually a universal signal		// then it should leave it in place.		sipQtSupport->qt_destroy_universal_slot(rx);		return res;	}	// Handle Python signals.	removeSlotFromPySigList(txSelf,sig,rxObj,slot);	Py_INCREF(Py_True);	return Py_True;}// Remove a slot from a transmitter's Python signal list.static void removeSlotFromPySigList(sipWrapper *txSelf,const char *sig,				    PyObject *rxObj,const char *slot){	sipPySig *ps;	if ((ps = findPySignal(txSelf,sig)) != NULL)	{		sipPySigRx **psrxp;		for (psrxp = &ps -> rxlist; *psrxp != NULL; psrxp = &(*psrxp) -> next)		{			sipPySigRx *psrx = *psrxp;			if (isSameSlot(&psrx -> rx,rxObj,slot))			{				*psrxp = psrx -> next;				sipFreePySigRx(psrx);				break;			}		}	}}// Free a sipSlot structure.static void freeSlot(sipSlot *slot){	if (slot->name != NULL)		sip_api_free(slot->name);	// Remove any weak reference.	Py_XDECREF(slot->weakSlot);}// Free a sipPySigRx structure on the heap.void sipFreePySigRx(sipPySigRx *rx){	freeSlot(&rx->rx);	sip_api_free(rx);}// Implement strdup() using sip_api_malloc().static char *sipStrdup(const char *s){	char *d;	if ((d = (char *)sip_api_malloc(strlen(s) + 1)) != NULL)		strcpy(d,s);	return d;}// Initialise a slot, returning 0 if there was no error.  If the signal was a// Qt signal, then the slot may be a Python signal or a Python slot.  If the// signal was a Python signal, then the slot may be anything.static int saveSlot(sipSlot *sp, PyObject *rxObj, const char *slot){	sp -> weakSlot = NULL;	if (slot == NULL)	{		sp -> name = NULL;		if (PyMethod_Check(rxObj))		{			// Python creates methods on the fly.  We could			// increment the reference count to keep it alive, but			// that would keep "self" alive as well and would			// probably be a circular reference.  Instead we			// remember the component parts and hope they are still			// valid when we re-create the method when we need it.			sipSaveMethod(&sp -> meth,rxObj);			// Notice if the class instance disappears.			sp -> weakSlot = getWeakRef(sp -> meth.mself);			// This acts a flag to say that the slot is a method.			sp -> pyobj = NULL;		}		else		{			PyObject *self;			// We know that it is another type of callable, ie. a			// function/builtin.			if (PyCFunction_Check(rxObj) &&			    (self = PyCFunction_GET_SELF(rxObj)) != NULL &&			    sip_api_wrapper_check(self))			{				// It is a wrapped C++ class method.  We can't				// keep a copy because they are generated on				// the fly and we can't take a reference as				// that may keep the instance (ie. self) alive.				// We therefore treat it as if the user had				// specified the slot at "obj, SLOT('meth()')"				// rather than "obj.meth" (see below).				char *meth;				// Get the method name.				meth = ((PyCFunctionObject *)rxObj) -> m_ml -> ml_name;				if ((sp -> name = (char *)sip_api_malloc(strlen(meth) + 2)) == NULL)					return -1;				// Copy the name and set the marker that it				// needs converting to a built-in method.				sp -> name[0] = '\0';				strcpy(&sp -> name[1],meth);				sp -> pyobj = self;				sp -> weakSlot = getWeakRef(self);			}			else			{				// It's unlikely that we will succeed in				// getting a weak reference to the slot, but				// there is no harm in trying (and future				// versions of Python may support references to				// more object types).				sp -> pyobj = rxObj;				sp -> weakSlot = getWeakRef(rxObj);			}		}	}	else if ((sp -> name = sipStrdup(slot)) == NULL)		return -1;	else if (isQtSlot(slot))	{		// The user has decided to connect a Python signal to a Qt slot		// and specified the slot as "obj, SLOT('meth()')" rather than		// "obj.meth".		char *tail;		// Remove any arguments.		if ((tail = strchr(sp -> name,'(')) != NULL)			*tail = '\0';		// A bit of a hack to indicate that this needs converting to a		// built-in method.		sp -> name[0] = '\0';		// Notice if the class instance disappears.		sp -> weakSlot = getWeakRef(rxObj);		sp -> pyobj = rxObj;	}	else		// It's a Qt signal.		sp -> pyobj = rxObj;	return 0;}// Return a weak reference to the given object.static PyObject *getWeakRef(PyObject *obj){	PyObject *wr;	if ((wr = PyWeakref_NewRef(obj,NULL)) == NULL)		PyErr_Clear();	return wr;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -