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

📄 qtlib.c

📁 这是关于RFC3261实现sip的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
// The SIP library code that implements the interface to the optional module// supplied Qt support.//// Copyright (c) 2006// 	Riverbank Computing Limited <info@riverbankcomputing.co.uk>// // This file is part of SIP.// // This copy of SIP is licensed for use under the terms of the SIP License// Agreement.  See the file LICENSE for more details.// // SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.#include <Python.h>#include <string.h>#include "sip.h"#include "sipint.h"// This is how Qt "types" signals and slots.#define	isQtSlot(s)	(*(s) == '1')#define	isQtSignal(s)	(*(s) == '2')static PyObject *py_sender = NULL;	// The last Python signal sender.static int isSameSlot(sipSlot *,PyObject *,const char *);static int emitQtSig(sipWrapper *,const char *,PyObject *);static int emitToSlotList(sipPySigRx *,PyObject *);static int addSlotToPySigList(sipWrapper *,const char *,PyObject *,const char *);static void removeSlotFromPySigList(sipWrapper *,const char *,PyObject *,const char *);static PyObject *getWeakRef(PyObject *obj);static sipPySig *findPySignal(sipWrapper *,const char *);static char *sipStrdup(const char *);static int saveSlot(sipSlot *sp, PyObject *rxObj, const char *slot);static sipSignature *parseSignature(const char *sig);static void *createUniversalSlot(sipWrapper *txSelf, const char *sig, PyObject *rxObj, const char *slot, const char **member);static void *findSignal(void *txrx, const char **sig);static void *newSignal(void *txrx, const char **sig);static void freeSlot(sipSlot *slot);// Return the most recent signal sender.PyObject *sip_api_get_sender(){	PyObject *sender;	const void *qt_sender;	// If there is a Qt sender then it is more recent than the last Python	// sender, so use it instead.	if ((qt_sender = sipQtSupport->qt_get_sender()) != NULL)		sender = sip_api_convert_from_instance(qt_sender, sipQObjectClass, NULL);	else	{		if ((sender = py_sender) == NULL)			sender = Py_None;		Py_INCREF(sender);	}	return sender;}// Release the resources held by a connection.void sip_api_free_connection(sipSlotConnection *conn){	freeSlot(&conn->sc_slot);}// Compare two connections and return TRUE if they are the same.int sip_api_same_connection(sipSlotConnection *conn, void *tx, const char *sig,			    PyObject *rxObj, const char *slot){	return (conn->sc_transmitter == tx &&		sipQtSupport->qt_same_name(conn->sc_signature->sg_signature, sig) &&		isSameSlot(&conn->sc_slot, rxObj, slot));}// Parse the signal arguments for a connection.static sipSignature *parseSignature(const char *sig){	static sipSignature *psig_list = NULL;	sipSignature *psig;	const char *sp, *ep;	// First see if it has already been parsed.  Note that both sides of a	// connection will probably be parsed twice because the function names	// will be different even though the signatures will probably be the	// same.  We could be more clever, the most saving is when repeatedly	// emitting a signal for which this is sufficient.	for (psig = psig_list; psig != NULL; psig = psig->sg_next)		if (sipQtSupport->qt_same_name(psig->sg_signature, sig))			return psig;	// Create a new one including space for the copy of the signature. */	if ((psig = (sipSignature *)sip_api_malloc(sizeof (sipSignature) + strlen(sig) + 1)) == NULL)		return NULL;	psig->sg_signature = (char *)&psig[1];	psig->sg_nrargs = 0;	psig->sg_args = 0;	// Find the start and end of the arguments.	sp = strchr(sig, '(');	ep = strrchr(sig, ')');	// If the signal isn't well formed we assume Qt will pick it up.	if (sp && ep && sp < ep)	{		// Copy the signature arguments while counting them and		// removing non-significant spaces.  Each argument is left as a		// '\0' terminated string.		char *dp = psig->sg_signature;		int depth = 0, nrcommas = 0, argstart = TRUE;		for (;;)		{			char ch = *++sp;			if (strchr(",*&)<>", ch))			{				// Backup over any previous trailing space.				if (dp > psig->sg_signature && dp[-1] == ' ')					--dp;				if (sp == ep)				{					*dp = '\0';					break;				}				if (ch == ',' && depth == 0)				{					*dp++ = '\0';					++nrcommas;					argstart = TRUE;				}				else				{					*dp++ = ch;					// Make sure commas in template					// arguments are ignored.					if (ch == '<')						++depth;					else if (ch == '>')						--depth;				}			}			else if (ch == ' ')			{				// Ignore leading and multiple spaces.				if (!argstart && dp[-1] != ' ')					*dp++ = ch;			}			else			{				*dp++ = ch;				argstart = FALSE;			}		}		// Handle the arguments now they are in a normal form.		if (*psig->sg_signature)		{			char *arg = psig->sg_signature;			int a;			// Allocate the space.			psig->sg_nrargs = nrcommas + 1;			if ((psig->sg_args = (sipSigArg *)sip_api_malloc(sizeof (sipSigArg) * psig->sg_nrargs)) == NULL)			{				sip_api_free(psig);				return -1;			}			for (a = 0; a < psig->sg_nrargs; ++a)			{				size_t btlen = 0;				int unsup, isref = FALSE, indir = 0;				sipSigArgType sat = unknown_sat;				// Find the start of the significant part of				// the type.				dp = arg;				if (strncmp(dp, "const ", 6) == 0)					dp += 6;				// Find the length of the base type, the number				// of indirections and if it is a reference.				for (ep = dp; *ep; ++ep)					if (*ep == '&')						isref = TRUE;					else if (*ep == '*')						++indir;					else						++btlen;				// Assume that anything other than a base type				// is unsupported.				unsup = (isref || indir);				// Parse the base type.				switch (btlen)				{				case 3:					if (strncmp(dp, "int", 3) == 0)						sat = int_sat;					break;				case 4:					if (strncmp(dp, "bool", 4) == 0)						sat = bool_sat;					else if (strncmp(dp, "long", 4) == 0)						sat = long_sat;					else if (strncmp(dp, "char", 4) == 0)					{						sat = (indir ? string_sat : char_sat);						unsup = (isref || indir > 1);					}					else if (strncmp(dp, "void", 4) == 0)					{						sat = void_sat;						unsup = (isref || indir != 1);					}					break;				case 5:					if (strncmp(dp, "float", 5) == 0)						sat = float_sat;					else if (strncmp(dp, "short", 5) == 0)						sat = short_sat;					break;				case 6:					if (strncmp(dp, "double", 6) == 0)						sat = double_sat;					break;				case 8:					if (strncmp(dp, "unsigned", 8) == 0)						sat = uint_sat;					else if (strncmp(dp, "QVariant", 8) == 0)					{						if (indir == 0)						{							sat = qvariant_sat;							unsup = FALSE;						}						else if (indir == 1)						{							sat = qvariantp_sat;							unsup = FALSE;						}					}					else if (strncmp(dp, "PyObject", 8) == 0 && indir == 1)					{						sat = pyobject_sat;						unsup = FALSE;					}					break;				case 9:					if (strncmp(dp, "long long", 9) == 0)						sat = longlong_sat;					break;				case 11:					if (strncmp(dp, "signed char", 11) == 0)					{						sat = (indir ? sstring_sat : schar_sat);						unsup = (isref || indir > 1);					}					break;				case 12:					if (strncmp(dp, "unsigned int", 12) == 0)						sat = uint_sat;					break;				case 13:					if (strncmp(dp, "unsigned long", 13) == 0)						sat = ulong_sat;					else if (strncmp(dp, "unsigned char", 13) == 0)					{						sat = (indir ? ustring_sat : uchar_sat);						unsup = (isref || indir > 1);					}					break;				case 14:					if (strncmp(dp, "unsigned short", 14) == 0)						sat = ushort_sat;					break;				case 18:					if (strncmp(dp, "unsigned long long", 18) == 0)						sat = ulonglong_sat;					break;				}				if (sat == unknown_sat)					sipFindSigArgType(dp, btlen, &psig->sg_args[a], indir);				else				{					if (unsup)						sat = unknown_sat;					psig->sg_args[a].atype = sat;				}				// Move to the start of the next argument.				arg += strlen(arg) + 1;			}		}	}	// Make a deep copy of the signal.	strcpy(psig->sg_signature, sig);	// Add it to the list so it can be re-used.	psig->sg_next = psig_list;	psig_list = psig;	return psig;}// Find an existing signal.static void *findSignal(void *txrx, const char **sig){	sipSignature *psig;	/*	 * Handle the trivial case where the Qt implementation doesn't support	 * universal signals.	 */	if (sipQtSupport->qt_is_qt_signal == NULL)		return txrx;	/* See if this a shortcircuited Python signal. */	if (strchr(*sig, '(') == NULL)		return sipQtSupport->qt_find_universal_signal_shortcut(txrx, *sig, sig);	/* See if the existing object can be used itself. */	if (sipQtSupport->qt_is_qt_signal(txrx, *sig))		return txrx;	if ((psig = parseSignature(*sig)) == NULL)		return NULL;	/* Find an ordinary universal signal. */	return sipQtSupport->qt_find_universal_signal(txrx, psig);}// Return a usable signal, creating a new universal signal if needed.static void *newSignal(void *txrx, const char **sig){	sipSignature *psig;	/*	 * Handle the trivial case where the Qt implementation doesn't support	 * universal signals.	 */	if (sipQtSupport->qt_is_qt_signal == NULL)		return txrx;	/* See if this a shortcircuited Python signal. */	if (strchr(*sig, '(') == NULL)		return sipQtSupport->qt_create_universal_signal_shortcut(txrx, *sig, sig);	/* See if the existing object can be used itself. */	if (sipQtSupport->qt_is_qt_signal(txrx, *sig))		return txrx;	if ((psig = parseSignature(*sig)) == NULL)		return NULL;	/* Create an ordinary universal signal. */	return sipQtSupport->qt_create_universal_signal(txrx, psig);}// Create a universal slot.  Returns a pointer to it or 0 if there was an// error.static void *createUniversalSlot(sipWrapper *txSelf, const char *sig,				 PyObject *rxObj, const char *slot,				 const char **member){	sipSlotConnection conn;	void *us;	// Initialise the connection.	conn.sc_transmitter = (txSelf ? sipGetAddress(txSelf) : 0);	// Save the real slot.	if (saveSlot(&conn.sc_slot, rxObj, slot) < 0)		return 0;	// Parse the signature and create the universal slot.	if ((conn.sc_signature = parseSignature(sig)) == NULL || (us = sipQtSupport->qt_create_universal_slot(txSelf, &conn, member)) == NULL)	{		sip_api_free_connection(&conn);		return 0;	}	return us;}// Emit a Python or Qt signal.int sip_api_emit_signal(PyObject *self,const char *sig,PyObject *sigargs){	sipPySig *ps;	void *tx;	sipWrapper *w = (sipWrapper *)self;	// Don't do anything if signals are blocked.  Qt signals would be	// blocked anyway, but this blocks Python signals as well.	if ((tx = sip_api_get_cpp_ptr(w, sipQObjectClass)) == NULL || sipQtSupport->qt_signals_blocked(tx))		return 0;	if (isQtSignal(sig))	{		sipSignature *psig;		/* Handle Qt implementations that emit using generated code. */		if (!sipQtSupport->qt_emit_signal)			return emitQtSig(w, sig, sigargs);		/* See if the signal is a shortcut. */		if (strchr(sig, '(') == NULL)			return sipQtSupport->qt_emit_signal_shortcut(tx, sig, sigargs);		if ((psig = parseSignature(sig)) == NULL)			return -1;		if (psig->sg_nrargs != PyTuple_GET_SIZE(sigargs))			PyErr_Format(PyExc_TypeError, "Signal has %d arguments, but %d given", psig->sg_nrargs, PyTuple_GET_SIZE(sigargs));		return sipQtSupport->qt_emit_signal(tx, psig, sigargs);	}	if ((ps = findPySignal(w,sig)) != NULL)	{		int rc;		// Forget the last Qt sender and remember this one.		sipQtSupport->qt_forget_sender();		py_sender = self;		rc = emitToSlotList(ps -> rxlist,sigargs);		// Forget this as a sender.		py_sender = NULL;		return rc;	}	return 0;}// Search the Python signal list for a signal.static sipPySig *findPySignal(sipWrapper *w,const char *sig){	sipPySig *ps;	for (ps = w -> pySigList; ps != NULL; ps = ps -> next)		if (sipQtSupport->qt_same_name(ps -> name,sig))			return ps;	return NULL;}// Search a signal table for a signal.  If found, call the emitter function// with the signal arguments.  Return 0 if the signal was emitted or <0 if// there was an error.static int emitQtSig(sipWrapper *w,const char *sig,PyObject *sigargs){	sipQtSignal *tab;	// Search the table.	for (tab = ((sipWrapperType *)(w -> ob_type)) -> type -> td_emit; tab -> st_name != NULL; ++tab)	{		const char *sp, *tp;		int found;		// Compare only the base name.		sp = &sig[1];		tp = tab -> st_name;		found = TRUE;		while (*sp != '\0' && *sp != '(' && *tp != '\0')			if (*sp++ != *tp++)			{				found = FALSE;				break;			}		if (found)			return (*tab -> st_emitfunc)(w,sigargs);	}	// It wasn't found if we got this far.	PyErr_Format(PyExc_NameError,"Invalid signal %s",&sig[1]);	return -1;}// Send a signal to a single slot (Qt or Python).int sip_api_emit_to_slot(sipSlot *slot, PyObject *sigargs){	PyObject *sa, *oxtype, *oxvalue, *oxtb, *sfunc, *newmeth, *sref;	// Keep some compilers quiet.	oxtype = oxvalue = oxtb = NULL;	// Fan out Qt signals.	if (slot -> name != NULL && slot -> name[0] != '\0')		return sip_api_emit_signal(slot -> pyobj,slot -> name,sigargs);	// Get the object to call, resolving any weak references.	if (slot -> weakSlot == NULL)		sref = NULL;	else if ((sref = PyWeakref_GetObject(slot -> weakSlot)) == NULL)		return -1;	else		Py_INCREF(sref);	if (sref == Py_None)	{		// If the real object has gone then we pretend everything is		// Ok.  This mimics the Qt behaviour of not caring if a		// receiving object has been deleted.		Py_DECREF(sref);		return 0;	}	if (slot -> pyobj == NULL)	{		PyObject *self = (sref != NULL ? sref : slot->meth.mself);		// See if any underlying C++ instance has gone.		if (self != NULL && sip_api_wrapper_check(self) && ((sipWrapper *)self)->u.cppPtr == NULL)		{			Py_XDECREF(sref);

⌨️ 快捷键说明

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