Example #1
0
/* A custom, fast, inlinable version of PyCFunction_Call() */
static PyObject *
call_cfunc(DispatcherObject *self, PyObject *cfunc, PyObject *args, PyObject *kws, PyObject *locals)
{
    PyCFunctionWithKeywords fn;
    PyThreadState *tstate;
    assert(PyCFunction_Check(cfunc));
    assert(PyCFunction_GET_FLAGS(cfunc) == METH_VARARGS | METH_KEYWORDS);
    fn = (PyCFunctionWithKeywords) PyCFunction_GET_FUNCTION(cfunc);
    tstate = PyThreadState_GET();
    if (tstate->use_tracing && tstate->c_profilefunc)
    {
        /*
         * The following code requires some explaining:
         *
         * We want the jit-compiled function to be visible to the profiler, so we
         * need to synthesize a frame for it.
         * The PyFrame_New() constructor doesn't do anything with the 'locals' value if the 'code's
         * 'CO_NEWLOCALS' flag is set (which is always the case nowadays).
         * So, to get local variables into the frame, we have to manually set the 'f_locals'
         * member, then call `PyFrame_LocalsToFast`, where a subsequent call to the `frame.f_locals`
         * property (by virtue of the `frame_getlocals` function in frameobject.c) will find them.
         */
        PyCodeObject *code = (PyCodeObject*)PyObject_GetAttrString((PyObject*)self, "__code__");
        PyObject *globals = PyDict_New();
        PyObject *builtins = PyEval_GetBuiltins();
        PyFrameObject *frame = NULL;
        PyObject *result = NULL;

        if (!code) {
            PyErr_Format(PyExc_RuntimeError, "No __code__ attribute found.");
            goto error;
        }
        /* Populate builtins, which is required by some JITted functions */
        if (PyDict_SetItemString(globals, "__builtins__", builtins)) {
            goto error;
        }
        frame = PyFrame_New(tstate, code, globals, NULL);
        if (frame == NULL) {
            goto error;
        }
        /* Populate the 'fast locals' in `frame` */
        Py_XDECREF(frame->f_locals);
        frame->f_locals = locals;
        Py_XINCREF(frame->f_locals);
        PyFrame_LocalsToFast(frame, 0);
        tstate->frame = frame;
        C_TRACE(result, fn(PyCFunction_GET_SELF(cfunc), args, kws));
        tstate->frame = frame->f_back;

    error:
        Py_XDECREF(frame);
        Py_XDECREF(globals);
        Py_XDECREF(code);
        return result;
    }
    else
        return fn(PyCFunction_GET_SELF(cfunc), args, kws);
}
Example #2
0
static bool getReceiver(QObject *source, PyObject* callback, QObject** receiver, PyObject** self)
{
    bool forceGlobalReceiver = false;
    if (PyMethod_Check(callback)) {
        *self = PyMethod_GET_SELF(callback);
        if (Shiboken::Converter<QObject*>::checkType(*self))
            *receiver = Shiboken::Converter<QObject*>::toCpp(*self);
        forceGlobalReceiver = isDecorator(callback, *self);
    } else if (PyCFunction_Check(callback)) {
        *self = PyCFunction_GET_SELF(callback);
        if (*self && Shiboken::Converter<QObject*>::checkType(*self))
            *receiver = Shiboken::Converter<QObject*>::toCpp(*self);
    } else if (PyCallable_Check(callback)) {
        // Ok, just a callable object
        *receiver = 0;
        *self = 0;
    }

    bool usingGlobalReceiver = !*receiver || forceGlobalReceiver;
    if (usingGlobalReceiver) {
        PySide::SignalManager& signalManager = PySide::SignalManager::instance();
        *receiver = signalManager.globalReceiver(source, callback);
    }

    return usingGlobalReceiver;
}
Example #3
0
SlotConnectorBase::SlotConnectorBase(PyObject* slot, int n_sig_args) {
	function = 0;
	klass = 0;
	PyObject* instance = 0;
	cfunction = 0;
	if (PyMethod_Check(slot)) {
		instance = PyMethod_GET_SELF(slot);

		klass =    PyMethod_GET_CLASS(slot);
		function = PyMethod_GET_FUNCTION(slot);
		Py_INCREF(klass);
		Py_INCREF(function);
		PyObject* func_code = PyObject_GetAttrString(function, "func_code");
		PyObject* co_argcount = PyObject_GetAttrString(func_code, "co_argcount");
		n_slot_args = PyInt_AsLong(co_argcount)-1;
		if (n_slot_args == -1) {
			PyErr_SetString(PyExc_TypeError, "Slot method should at least have a 'self' argument");
			return;
		}
		core = ((Wt::WObject*)(((PyCPPClassInstance*)instance)->proxy->getCoreAsVoid()));
		Py_DECREF(func_code);
		Py_DECREF(co_argcount);
	}
	else if PyCFunction_Check(slot) {
		instance = PyCFunction_GET_SELF(slot);
		cfunction = PyCFunction_GET_FUNCTION(slot);
		flags = PyCFunction_GET_FLAGS(slot);
		n_slot_args = PyCFunction_GET_NARGS(slot);
		core = ((Wt::WObject*)(((PyCPPClassInstance*)instance)->proxy->getCoreAsVoid()));
	}
	else {
Example #4
0
PyObject *
PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
{
    PyCFunctionObject* f = (PyCFunctionObject*)func;
    PyCFunction meth = PyCFunction_GET_FUNCTION(func);
    PyObject *self = PyCFunction_GET_SELF(func);
    Py_ssize_t size;

    switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
    case METH_VARARGS:
        if (kw == NULL || PyDict_Size(kw) == 0)
            return (*meth)(self, arg);
        break;
    case METH_VARARGS | METH_KEYWORDS:
    case METH_OLDARGS | METH_KEYWORDS:
        return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
    case METH_NOARGS:
        if (kw == NULL || PyDict_Size(kw) == 0) {
            size = PyTuple_GET_SIZE(arg);
            if (size == 0)
                return (*meth)(self, NULL);
            PyErr_Format(PyExc_TypeError,
                "%.200s() takes no arguments (%zd given)",
                f->m_ml->ml_name, size);
            return NULL;
        }
        break;
    case METH_O:
        if (kw == NULL || PyDict_Size(kw) == 0) {
            size = PyTuple_GET_SIZE(arg);
            if (size == 1)
                return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
            PyErr_Format(PyExc_TypeError,
                "%.200s() takes exactly one argument (%zd given)",
                f->m_ml->ml_name, size);
            return NULL;
        }
        break;
    case METH_OLDARGS:
        /* the really old style */
        if (kw == NULL || PyDict_Size(kw) == 0) {
            size = PyTuple_GET_SIZE(arg);
            if (size == 1)
                arg = PyTuple_GET_ITEM(arg, 0);
            else if (size == 0)
                arg = NULL;
            return (*meth)(self, arg);
        }
        break;
    default:
        PyErr_BadInternalCall();
        return NULL;
    }
    PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
                 f->m_ml->ml_name);
    return NULL;
}
Example #5
0
PyObject *
PyCFunction_GetSelf(PyObject *op)
{
    if (!PyCFunction_Check(op)) {
        PyErr_BadInternalCall();
        return NULL;
    }
    return PyCFunction_GET_SELF(op);
}
Example #6
0
static PyObject *
meth_get__self__(PyCFunctionObject *m, void *closure)
{
    PyObject *self;

    self = PyCFunction_GET_SELF(m);
    if (self == NULL)
        self = Py_None;
    Py_INCREF(self);
    return self;
}
PyObject *
PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
{
    PyCFunctionObject* f = (PyCFunctionObject*)func;
    PyCFunction meth = PyCFunction_GET_FUNCTION(func);
    PyObject *self = PyCFunction_GET_SELF(func);
    Py_ssize_t size;

    switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
    case METH_VARARGS:
        if (kw == NULL || PyDict_Size(kw) == 0)
            return (*meth)(self, arg);
        break;
    case METH_VARARGS | METH_KEYWORDS:
        return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
    case METH_NOARGS:
        if (kw == NULL || PyDict_Size(kw) == 0) {
            size = PyTuple_GET_SIZE(arg);
            if (size == 0)
                return (*meth)(self, NULL);
            PyErr_Format(PyExc_TypeError,
                "%.200s() takes no arguments (%zd given)",
                f->m_ml->ml_name, size);
            return NULL;
        }
        break;
    case METH_O:
        if (kw == NULL || PyDict_Size(kw) == 0) {
            size = PyTuple_GET_SIZE(arg);
            if (size == 1)
                return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
            PyErr_Format(PyExc_TypeError,
                "%.200s() takes exactly one argument (%zd given)",
                f->m_ml->ml_name, size);
            return NULL;
        }
        break;
    default:
        PyErr_SetString(PyExc_SystemError, "Bad call flags in "
                        "PyCFunction_Call. METH_OLDARGS is no "
                        "longer supported!");

        return NULL;
    }
    PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
                 f->m_ml->ml_name);
    return NULL;
}
Example #8
0
/*
 * Compare two slots to see if they are the same.
 */
int sip_api_same_slot(const sipSlot *sp, PyObject *rxObj, const char *slot)
{
    assert(sipQtSupport);
    assert(sipQtSupport->qt_same_name);

    /* See if they are signals or Qt slots, ie. they have a name. */
    if (slot != NULL)
    {
        if (sp->name == NULL || sp->name[0] == '\0')
            return 0;

        return (sipQtSupport->qt_same_name(sp->name, slot) && sp->pyobj == rxObj);
    }

    /* See if they are pure Python methods. */
    if (PyMethod_Check(rxObj))
    {
        if (sp->pyobj != NULL)
            return 0;

        return (sp->meth.mfunc == PyMethod_GET_FUNCTION(rxObj)
                && sp->meth.mself == PyMethod_GET_SELF(rxObj)
#if PY_MAJOR_VERSION < 3
                && sp->meth.mclass == PyMethod_GET_CLASS(rxObj)
#endif
                );
    }

    /* See if they are wrapped C++ methods. */
    if (PyCFunction_Check(rxObj))
    {
        if (sp->name == NULL || sp->name[0] != '\0')
            return 0;

        return (sp->pyobj == PyCFunction_GET_SELF(rxObj) &&
                strcmp(&sp->name[1], ((PyCFunctionObject *)rxObj)->m_ml->ml_name) == 0);
    }

    /* The objects must be the same. */
    return (sp->pyobj == rxObj);
}
Example #9
0
/*
 * 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.
 */
int sip_api_save_slot(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 &&
                PyObject_TypeCheck(self, (PyTypeObject *)&sipSimpleWrapper_Type))
            {
                /*
                 * 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).
                 */

                const 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
            {
                /*
                 * Give the slot an extra reference to keep it alive and
                 * remember we have done so by treating weakSlot specially.
                 */
                Py_INCREF(rxObj);
                sp->pyobj = rxObj;

                Py_INCREF(Py_True);
                sp->weakSlot = Py_True;
            }
        }
    }
    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;
}
Example #10
0
static PyObject *
call_function(PyObject ***pp_stack, int oparg)
{
	int na = oparg & 0xff;
	int nk = (oparg>>8) & 0xff;
	int n = na + 2 * nk;
	PyObject **pfunc = (*pp_stack) - n - 1;
	PyObject *func = *pfunc;
	PyObject *x, *w;

	/* Always dispatch PyCFunction first, because these are
	   presumed to be the most frequent callable object.
	*/
	if (PyCFunction_Check(func) && nk == 0) {
		int flags = PyCFunction_GET_FLAGS(func);
		if (flags & (METH_NOARGS | METH_O)) {
			PyCFunction meth = PyCFunction_GET_FUNCTION(func);
			PyObject *self = PyCFunction_GET_SELF(func);
			if (flags & METH_NOARGS && na == 0) 
				x = (*meth)(self, NULL);
			else if (flags & METH_O && na == 1) {
				PyObject *arg = EXT_POP(*pp_stack);
				x = (*meth)(self, arg);
				Py_DECREF(arg);
			}
			else {
				err_args(func, flags, na);
				x = NULL;
			}
		}
		else {
			PyObject *callargs;
			callargs = load_args(pp_stack, na);
			x = PyCFunction_Call(func, callargs, NULL);
			Py_XDECREF(callargs); 
		} 
	} else {
		if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
			/* optimize access to bound methods */
			PyObject *self = PyMethod_GET_SELF(func);
			Py_INCREF(self);
			func = PyMethod_GET_FUNCTION(func);
			Py_INCREF(func);
			Py_DECREF(*pfunc);
			*pfunc = self;
			na++;
			n++;
		} else
			Py_INCREF(func);
		if (PyFunction_Check(func))
			x = fast_function(func, pp_stack, n, na, nk);
		else 
			x = do_call(func, pp_stack, na, nk);
		Py_DECREF(func);
	}
	
	/* What does this do? */
	while ((*pp_stack) > pfunc) {
		w = EXT_POP(*pp_stack);
		Py_DECREF(w);
	}
	return x;
}
// Get the receiver QObject from the slot (if there is one) and its signature
// (if it wraps a Qt slot).  A Python exception will be raised if there was an
// error.
static QObject *get_receiver(qpycore_pyqtBoundSignal *bs, PyObject *slot_obj,
        QByteArray &name)
{
    PyObject *rx_self, *decorations;
    QByteArray rx_name;
    bool try_qt_slot;
    Chimera::Signature *signature = bs->unbound_signal->signature;

    decorations = 0;

    if (PyMethod_Check(slot_obj))
    {
        rx_self = PyMethod_GET_SELF(slot_obj);

        PyObject *f = PyMethod_GET_FUNCTION(slot_obj);
        Q_ASSERT(PyFunction_Check(f));

        PyObject *f_name_obj = ((PyFunctionObject *)f)->func_name;
        const char *f_name = sipString_AsASCIIString(&f_name_obj);
        Q_ASSERT(f_name);

        rx_name = f_name;
        Py_DECREF(f_name_obj);

        // See if this has been decorated.
        decorations = PyObject_GetAttr(f, qpycore_signature_attr_name);

        if (decorations)
        {
            try_qt_slot = true;

            // It's convenient to do this here as it's not going to disappear.
            Py_DECREF(decorations);
        }
        else
        {
            try_qt_slot = false;
        }

        Py_XINCREF(rx_self);
    }
    else if (PyCFunction_Check(slot_obj))
    {
        rx_self = PyCFunction_GET_SELF(slot_obj);
        rx_name = ((PyCFunctionObject *)slot_obj)->m_ml->ml_name;

        // We actually want the C++ name which may (in theory) be completely
        // different.  However this will cope with the exec_ case which is
        // probably good enough.
        if (rx_name.endsWith('_'))
            rx_name.chop(1);

        try_qt_slot = true;

        Py_XINCREF(rx_self);
    }
    else
    {
        static PyObject *partial = 0;

        // Get the functools.partial type object if we haven't already got it.
        if (!partial)
        {
            PyObject *functools = PyImport_ImportModule("functools");

            if (functools)
            {
                partial = PyObject_GetAttrString(functools, "partial");
                Py_DECREF(functools);
            }
        }

        // If we know about functools.partial then remove the outer partials to
        // get to the original function.
        if (partial && PyObject_IsInstance(slot_obj, partial))
        {
            PyObject *func = slot_obj;

            Py_INCREF(func);

            do
            {
                PyObject *subfunc = PyObject_GetAttrString(func, "func");

                Py_DECREF(func);

                // This should never happen.
                if (!subfunc)
                    return 0;

                func = subfunc;
            }
            while (PyObject_IsInstance(func, partial));

            if (PyMethod_Check(func))
                rx_self = PyMethod_GET_SELF(func);
            else if (PyCFunction_Check(func))
                rx_self = PyCFunction_GET_SELF(func);
            else
                rx_self = 0;

            Py_XINCREF(rx_self);
            Py_DECREF(func);

            try_qt_slot = false;
        }
        else
        {
            rx_self = 0;
        }
    }
 
    if (!rx_self)
        return 0;

    int iserr = 0;
    void *rx = sipForceConvertToType(rx_self, sipType_QObject, 0,
            SIP_NO_CONVERTORS, 0, &iserr);

    Py_DECREF(rx_self);

    PyErr_Clear();

    if (iserr)
        return 0;

    QObject *rx_qobj = reinterpret_cast<QObject *>(rx);

    // If there might be a Qt slot that can handle the arguments (or a subset
    // of them) then use it.  Otherwise we will fallback to using a proxy.
    if (try_qt_slot)
    {
        for (int ol = signature->parsed_arguments.count(); ol >= 0; --ol)
        {
            // If there are decorations then we compare the signal's signature
            // against them so that we distinguish between Python types that
            // are passed to Qt as PyQt_PyObject objects.  Qt will not make the
            // distinction.  If there are no decorations then let Qt determine
            // if a slot is available.
            if (decorations)
                name = slot_signature_from_decorations(signature, decorations,
                        ol);
            else
                name = slot_signature_from_metaobject(signature,
                        rx_qobj->metaObject(), rx_name, ol);

            if (!name.isEmpty())
            {
                // Prepend the magic slot marker.
                name.prepend('1');
                break;
            }
        }
    }

    return rx_qobj;
}
Example #12
0
PyObject *
PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
{
	PyCFunctionObject* f = (PyCFunctionObject*)func;
	PyCFunction meth = PyCFunction_GET_FUNCTION(func);
	PyObject *self = PyCFunction_GET_SELF(func);
	Py_ssize_t size;

	switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
	case METH_VARARGS:
		if (kw == NULL || PyDict_Size(kw) == 0)
			return (*meth)(self, arg);
		break;
	case METH_VARARGS | METH_KEYWORDS:
	case METH_OLDARGS | METH_KEYWORDS:
		return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
	case METH_ARG_RANGE:
	{
		if (kw == NULL || PyDict_Size(kw) == 0) {
			PyObject *args[PY_MAX_ARITY] = {NULL};
			int min_arity = PyCFunction_GET_MIN_ARITY(func);
			int max_arity = PyCFunction_GET_MAX_ARITY(func);
			size = PyTuple_GET_SIZE(arg);
			switch (size) {
				default:
					PyErr_BadInternalCall();
					return NULL;
				case 3: args[2] = PyTuple_GET_ITEM(arg, 2);
				case 2: args[1] = PyTuple_GET_ITEM(arg, 1);
				case 1: args[0] = PyTuple_GET_ITEM(arg, 0);
				case 0: break;
			}

			/* But wait, you ask, what about {un,bin}ary functions?
			   Aren't we passing more arguments than it expects?
			   Yes, but C allows this. Go C. */
			if (min_arity <= size && size <= max_arity)
				return (*(PyCFunctionThreeArgs)meth)
				       (self, args[0], args[1], args[2]);

			if (max_arity == min_arity)
				PyErr_Format(PyExc_TypeError,
					"%.200s() takes exactly %d argument(s)"
					" (%zd given)",
					f->m_ml->ml_name, max_arity, size);
			else
				PyErr_Format(PyExc_TypeError,
					"%.200s() takes %d-%d arguments"
					" (%zd given)",
					f->m_ml->ml_name,
					min_arity, max_arity, size);

			return NULL;
		}
		break;
	}
	case METH_OLDARGS:
		/* the really old style */
		if (kw == NULL || PyDict_Size(kw) == 0) {
			size = PyTuple_GET_SIZE(arg);
			if (size == 1)
				arg = PyTuple_GET_ITEM(arg, 0);
			else if (size == 0)
				arg = NULL;
			return (*meth)(self, arg);
		}
		break;
	/* METH_O is deprecated; PyCFunction_NewEx is supposed to convert it to
	   METH_ARG_RANGE and set ml_{min,max}_arity correctly. */
	case METH_O:
	default:
		PyErr_BadInternalCall();
		return NULL;
	}
	PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
		     f->m_ml->ml_name);
	return NULL;
}
// Get the receiver QObject from the slot (if there is one) and its signature
// (if it wraps a Qt slot).  A Python exception will be raised if there was an
// error.
static QObject *get_receiver(Chimera::Signature *overload, PyObject *slot_obj,
        QByteArray &name)
{
    PyObject *rx_self, *decorations;
    QByteArray rx_name;
    bool try_qt_slot;

    decorations = 0;

    if (PyMethod_Check(slot_obj))
    {
        rx_self = PyMethod_GET_SELF(slot_obj);

        PyObject *f = PyMethod_GET_FUNCTION(slot_obj);
        Q_ASSERT(PyFunction_Check(f));

        PyObject *f_name_obj = ((PyFunctionObject *)f)->func_name;
        const char *f_name = sipString_AsASCIIString(&f_name_obj);
        Q_ASSERT(f_name);

        rx_name = f_name;
        Py_DECREF(f_name_obj);

        // See if this has been decorated.
        decorations = PyObject_GetAttr(f, qpycore_signature_attr_name);

        if (decorations)
        {
            try_qt_slot = true;

            // It's convenient to do this here as it's not going to disappear.
            Py_DECREF(decorations);
        }
        else
        {
            try_qt_slot = false;
        }
    }
    else if (PyCFunction_Check(slot_obj))
    {
        rx_self = PyCFunction_GET_SELF(slot_obj);
        rx_name = ((PyCFunctionObject *)slot_obj)->m_ml->ml_name;

        // We actually want the C++ name which may (in theory) be completely
        // different.  However this will cope with the exec_ case which is
        // probably good enough.
        if (rx_name.endsWith('_'))
            rx_name.chop(1);

        try_qt_slot = true;
    }
    else
    {
        rx_self = 0;
    }
 
    if (!rx_self)
        return 0;

    int iserr = 0;
    void *rx = sipForceConvertToType(rx_self, sipType_QObject, 0,
            SIP_NO_CONVERTORS, 0, &iserr);

    PyErr_Clear();

    if (iserr)
        return 0;

    QObject *rx_qobj = reinterpret_cast<QObject *>(rx);

    // If there might be a Qt slot that can handle the arguments (or a subset
    // of them) then use it.  Otherwise we will fallback to using a proxy.
    if (try_qt_slot)
    {
        for (int ol = overload->parsed_arguments.count(); ol >= 0; --ol)
        {
            // If there are decorations then we compare the signal's signature
            // against them so that we distinguish between Python types that
            // are passed to Qt as PyQt_PyObject objects.  Qt will not make the
            // distinction.  If there are no decorations then let Qt determine
            // if a slot is available.
            if (decorations)
                name = slot_signature_from_decorations(overload, decorations,
                        ol);
            else
                name = slot_signature_from_metaobject(overload,
                        rx_qobj->metaObject(), rx_name, ol);

            if (!name.isEmpty())
            {
                // Prepend the magic slot marker.
                name.prepend('1');
                break;
            }
        }
    }

    return rx_qobj;
}
Example #14
0
PyObject *
PyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwds)
{
    PyCFunctionObject* f = (PyCFunctionObject*)func;
    PyCFunction meth = PyCFunction_GET_FUNCTION(func);
    PyObject *self = PyCFunction_GET_SELF(func);
    PyObject *arg, *res;
    Py_ssize_t size;
    int flags;

    /* PyCFunction_Call() must not be called with an exception set,
       because it may clear it (directly or indirectly) and so the
       caller loses its exception */
    assert(!PyErr_Occurred());

    flags = PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST);

    if (flags == (METH_VARARGS | METH_KEYWORDS)) {
        res = (*(PyCFunctionWithKeywords)meth)(self, args, kwds);
    }
    else {
        if (kwds != NULL && PyDict_Size(kwds) != 0) {
            PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
                         f->m_ml->ml_name);
            return NULL;
        }

        switch (flags) {
        case METH_VARARGS:
            res = (*meth)(self, args);
            break;

        case METH_NOARGS:
            size = PyTuple_GET_SIZE(args);
            if (size != 0) {
                PyErr_Format(PyExc_TypeError,
                    "%.200s() takes no arguments (%zd given)",
                    f->m_ml->ml_name, size);
                return NULL;
            }

            res = (*meth)(self, NULL);
            break;

        case METH_O:
            size = PyTuple_GET_SIZE(args);
            if (size != 1) {
                PyErr_Format(PyExc_TypeError,
                    "%.200s() takes exactly one argument (%zd given)",
                    f->m_ml->ml_name, size);
                return NULL;
            }

            arg = PyTuple_GET_ITEM(args, 0);
            res = (*meth)(self, arg);
            break;

        default:
            PyErr_SetString(PyExc_SystemError,
                            "Bad call flags in PyCFunction_Call. "
                            "METH_OLDARGS is no longer supported!");
            return NULL;
        }
    }

    return _Py_CheckFunctionResult(func, res, NULL);
}
Example #15
0
PyObject *
PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
{
    STACKLESS_GETARG();
    PyCFunctionObject* f = (PyCFunctionObject*)func;
    PyCFunction meth = PyCFunction_GET_FUNCTION(func);
    PyObject *self = PyCFunction_GET_SELF(func);
    Py_ssize_t size;

#ifdef STACKLESS
    switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_STACKLESS)) {
#else
    switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
#endif
    case METH_VARARGS:
        if (kw == NULL || PyDict_Size(kw) == 0)
            WRAP_RETURN( (*meth)(self, arg) )
        break;
    case METH_VARARGS | METH_KEYWORDS:
        WRAP_RETURN( (*(PyCFunctionWithKeywords)meth)(self, arg, kw) )
    case METH_NOARGS:
        if (kw == NULL || PyDict_Size(kw) == 0) {
            size = PyTuple_GET_SIZE(arg);
            if (size == 0)
                WRAP_RETURN( (*meth)(self, NULL) )
            PyErr_Format(PyExc_TypeError,
                "%.200s() takes no arguments (%zd given)",
                f->m_ml->ml_name, size);
            return NULL;
        }
        break;
    case METH_O:
        if (kw == NULL || PyDict_Size(kw) == 0) {
            size = PyTuple_GET_SIZE(arg);
            if (size == 1)
                WRAP_RETURN( (*meth)(self, PyTuple_GET_ITEM(arg, 0)) )
            PyErr_Format(PyExc_TypeError,
                "%.200s() takes exactly one argument (%zd given)",
                f->m_ml->ml_name, size);
            return NULL;
        }
        break;
    default:
        PyErr_SetString(PyExc_SystemError, "Bad call flags in "
                "PyCFunction_Call. METH_OLDARGS is no "
                "longer supported!");
            
        return NULL;
    }
    PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
             f->m_ml->ml_name);
    return NULL;
}

/* Methods (the standard built-in methods, that is) */

static void
meth_dealloc(PyCFunctionObject *m)
{
    _PyObject_GC_UNTRACK(m);
    Py_XDECREF(m->m_self);
    Py_XDECREF(m->m_module);
    if (numfree < PyCFunction_MAXFREELIST) {
        m->m_self = (PyObject *)free_list;
        free_list = m;
        numfree++;
    }
    else {
        PyObject_GC_Del(m);
    }
}