/**
 *	This method creates a Vector3Generator, given a python list object. It
 *	uses the parsePythonTuple static methods of each of its children in
 *	order to parse the details.
 *
 *	@param args		The list of parameters passed from Python. This should
 *					be a list with a string for the head. The string
 *					represents the type of the vector generator desired.
 *					The tail of the list is passed to the specific generator
 *					to be parsed further.
 *
 *	@return	A pointer to the newly created vector generator if everything was
 *			created without problems. NULL, otherwise.
 */
VectorGenerator *VectorGenerator::parseFromPython( PyObject *args )
{
	BW_GUARD;
	// PySequence_Check( args )
	// PySequence_GetItem( args, i ) // new reference
	PyObject *pGeneratorType = PyList_GetItem( args, 0 );

	// Get the string containing the type of the VectorGenerator desired.
	// It should be found in the head of the arguments list.
	if ( ( pGeneratorType != NULL ) && PyString_Check( pGeneratorType ) )
	{
		// Retrieve the tail of the list. The argsAsTuple object is not a
		// borrowed reference so it has to be deferenced. The same applies to
		// the tail object.
		PyObject *argsAsTuple = PyList_AsTuple( args );
		PyObject *tail = PyTuple_GetSlice( argsAsTuple, 1,
			PyTuple_Size( argsAsTuple ) );
		Py_DECREF( argsAsTuple );

		char *generatorType = PyString_AsString( pGeneratorType );

		// Based on the type of the VectorGenerator, parse the rest of the
		// list. The base class does not know how to do this, it only knows
		// what identifies a derived class - once it identifies which class
		// is requested, it passed the information on the the derived classes.
		if ( !_stricmp( generatorType, "Point" ) )
		{
			return PointVectorGenerator::parsePythonTuple( tail );
		}
		else if  ( !_stricmp( generatorType, "Line" ) )
		{
			return LineVectorGenerator::parsePythonTuple( tail );
		}
		else if  ( !_stricmp( generatorType, "Cylinder" ) )
		{
			return CylinderVectorGenerator::parsePythonTuple( tail );
		}
		else if  ( !_stricmp( generatorType, "Sphere" ) )
		{
			return SphereVectorGenerator::parsePythonTuple( tail );
		}
		else if  ( !_stricmp( generatorType, "Box" ) )
		{
			return BoxVectorGenerator::parsePythonTuple( tail );
		}
		else
		{
			PyErr_Format( PyExc_TypeError,
				"VectorGenerator: Unknown or unregistered generator %s.",
				generatorType );
			return NULL;
		}
	}
	else
	{
		PyErr_SetString( PyExc_TypeError, "VectorGenerator:"
			"VectorGenerator name <string> required at head of list." );
		return NULL;
	}
}
Example #2
0
static PyObject* call(PyObject* unused, PyObject* args) {
    PyObject* func = PyTuple_GetItem(args, 0);
    PyObject* fargs = PyTuple_GetSlice(args, 1, PyTuple_Size(args));
    PyObject* ret = PyAutoFunction_CallByName(PyString_AsString(func), fargs);
    Py_DECREF(fargs);
    return ret;
}
Example #3
0
 /** slice, [i:j].
  * @throw type_err
  */
 obj sub(int i, int j = std::numeric_limits<int>::max())const
 {
     PyObject* p = PyTuple_GetSlice(_p, i, j);
     if(!p)
         throw type_err("sub failed");
     return p;
 }
Example #4
0
// Register a timed callback.
// First argument should be the time in picoseconds
// Second argument is the function to call
// Remaining arguments and keyword arguments are to be passed to the callback
static PyObject *register_timed_callback(PyObject *self, PyObject *args)
{
    FENTER

    PyObject *fArgs;
    PyObject *function;
    gpi_sim_hdl hdl;
    uint64_t time_ps;

    p_callback_data callback_data_p;

    Py_ssize_t numargs = PyTuple_Size(args);

    if (numargs < 2) {
        fprintf(stderr, "Attempt to register timed callback without enough arguments!\n");
        return NULL;
    }

    // Extract the time
    PyObject *pTime = PyTuple_GetItem(args, 0);
    time_ps = PyLong_AsLongLong(pTime);

    // Extract the callback function
    function = PyTuple_GetItem(args, 1);
    if (!PyCallable_Check(function)) {
        fprintf(stderr, "Attempt to register timed callback without passing a callable callback!\n");
        return NULL;
    }
    Py_INCREF(function);

    // Remaining args for function
    fArgs = PyTuple_GetSlice(args, 2, numargs);   // New reference
    if (fArgs == NULL) {
        return NULL;
    }

    callback_data_p = (p_callback_data)malloc(sizeof(s_callback_data));
    if (callback_data_p == NULL) {
        return PyErr_NoMemory();
    }

    // Set up the user data (no more python API calls after this!)
    callback_data_p->_saved_thread_state = PyThreadState_Get();
    callback_data_p->id_value = COCOTB_ACTIVE_ID;
    callback_data_p->function = function;
    callback_data_p->args = fArgs;
    callback_data_p->kwargs = NULL;

    hdl = gpi_register_timed_callback((gpi_function_t)handle_gpi_callback, callback_data_p, time_ps);

    // Check success
    PyObject *rv = PyLong_FromVoidPtr(hdl);
    FEXIT

    return rv;
}
Example #5
0
static PyObject *
GMPy_Context_Digits(PyObject *self, PyObject *args)
{
    PyObject *arg0, *tuple, *temp, *result;
    Py_ssize_t argc;

    argc = PyTuple_GET_SIZE(args);
    if (argc == 0) {
        TYPE_ERROR("digits() requires at least one argument");
        return NULL;
    }

    if (argc > 3) {
        TYPE_ERROR("digits() accepts at most three arguments");
        return NULL;
    }

    arg0 = PyTuple_GET_ITEM(args, 0);
    if (!(tuple = PyTuple_GetSlice(args, 1, argc))) {
        return NULL;
    }

    if (IS_INTEGER(arg0)) {
        temp = (PyObject*)GMPy_MPZ_From_Integer(arg0, NULL);
        result = GMPy_MPZ_Digits_Method(temp, tuple);
        Py_DECREF(temp);
        Py_DECREF(tuple);
        return result;
    }
    if (IS_RATIONAL(arg0)) {
        temp = (PyObject*)GMPy_MPQ_From_Rational(arg0, NULL);
        result = GMPy_MPQ_Digits_Method(temp, tuple);
        Py_DECREF(temp);
        Py_DECREF(tuple);
        return result;
    }
    if (IS_REAL(arg0)) {
        temp = (PyObject*)GMPy_MPFR_From_Real(arg0, 1, NULL);
        result = GMPy_MPFR_Digits_Method(temp, tuple);
        Py_DECREF(temp);
        Py_DECREF(tuple);
        return result;
    }
    if (IS_COMPLEX(arg0)) {
        temp = (PyObject*)GMPy_MPC_From_Complex(arg0, 1, 1, NULL);
        result = GMPy_MPC_Digits_Method(temp, tuple);
        Py_DECREF(temp);
        Py_DECREF(tuple);
        return result;
    }

    TYPE_ERROR("digits() argument type not supported");
    return NULL;
}
Example #6
0
static PyObject *
atexit_register(PyObject *self, PyObject *args, PyObject *kwargs)
{
    atexitmodule_state *modstate;
    atexit_callback *new_callback;
    PyObject *func = NULL;

    modstate = GET_ATEXIT_STATE(self);

    if (modstate->ncallbacks >= modstate->callback_len) {
        atexit_callback **r;
        modstate->callback_len += 16;
        r = (atexit_callback**)PyMem_Realloc(modstate->atexit_callbacks,
                                      sizeof(atexit_callback*) * modstate->callback_len);
        if (r == NULL)
            return PyErr_NoMemory();
        modstate->atexit_callbacks = r;
    }

    if (PyTuple_GET_SIZE(args) == 0) {
        PyErr_SetString(PyExc_TypeError,
                "register() takes at least 1 argument (0 given)");
        return NULL;
    }

    func = PyTuple_GET_ITEM(args, 0);
    if (!PyCallable_Check(func)) {
        PyErr_SetString(PyExc_TypeError,
                "the first argument must be callable");
        return NULL;
    }

    new_callback = PyMem_Malloc(sizeof(atexit_callback));
    if (new_callback == NULL)
        return PyErr_NoMemory();

    new_callback->args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
    if (new_callback->args == NULL) {
        PyMem_Free(new_callback);
        return NULL;
    }
    new_callback->func = func;
    new_callback->kwargs = kwargs;
    Py_INCREF(func);
    Py_XINCREF(kwargs);

    modstate->atexit_callbacks[modstate->ncallbacks++] = new_callback;

    Py_INCREF(func);
    return func;
}
Example #7
0
static PyObject *register_rwsynch_callback(PyObject *self, PyObject *args)
{
    FENTER

    PyObject *fArgs;
    PyObject *function;
    gpi_sim_hdl hdl;

    p_callback_data callback_data_p;

    Py_ssize_t numargs = PyTuple_Size(args);

    if (numargs < 1) {
        fprintf(stderr, "Attempt to register ReadOnly callback with!\n");
        return NULL;
    }

    // Extract the callback function
    function = PyTuple_GetItem(args, 0);
    if (!PyCallable_Check(function)) {
        fprintf(stderr, "Attempt to register ReadOnly without supplying a callback!\n");
        return NULL;
    }
    Py_INCREF(function);

    // Remaining args for function
    fArgs = PyTuple_GetSlice(args, 1, numargs);   // New reference
    if (fArgs == NULL) {
        return NULL;
    }

    callback_data_p = (p_callback_data)malloc(sizeof(s_callback_data));
    if (callback_data_p == NULL) {
        return PyErr_NoMemory();
    }

    // Set up the user data (no more python API calls after this!)
    callback_data_p->_saved_thread_state = PyThreadState_Get();
    callback_data_p->id_value = COCOTB_ACTIVE_ID;
    callback_data_p->function = function;
    callback_data_p->args = fArgs;
    callback_data_p->kwargs = NULL;

    hdl = gpi_register_readwrite_callback((gpi_function_t)handle_gpi_callback, callback_data_p);

    PyObject *rv = PyLong_FromVoidPtr(hdl);
    FEXIT

    return rv;
}
static PyObject *
wrap_slice(PyObject *self, Py_ssize_t start, Py_ssize_t end)
{
    PyObject *obj = Proxy_GET_OBJECT(self);
    if (PyList_Check(obj)) {
        return PyList_GetSlice(obj, start, end);
    }
    else if (PyTuple_Check(obj)) {
        return PyTuple_GetSlice(obj, start, end);
    }
    else {
        return PySequence_GetSlice(obj, start, end);
    }
}
PyObject *PythonQtMemberFunction_Call(PythonQtSlotInfo* info, PyObject* m_self, PyObject *args, PyObject *kw)
{
  if (PyObject_TypeCheck(m_self, &PythonQtInstanceWrapper_Type)) {
    PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) m_self;
    if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
      QString error = QString("Trying to call '") + info->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
      PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
      return NULL;
    } else {
      return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
    }
  } else if (m_self->ob_type == &PythonQtClassWrapper_Type) {
    PythonQtClassWrapper* type = (PythonQtClassWrapper*) m_self;
    if (info->isClassDecorator()) {
      return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
    } else {
      // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
      Py_ssize_t argc = PyTuple_Size(args);
      if (argc>0) {
        PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
        if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
          && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
          PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
          if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
            QString error = QString("Trying to call '") + info->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
            PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
            return NULL;
          }
          // strip the first argument...
          PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
          PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
          Py_DECREF(newargs);
          return result;
        } else {
          // first arg is not of correct type!
          QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
          PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
          return NULL;
        }
      } else {
        // wrong number of args
        QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
        PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
        return NULL;
      }
    }
  }
  return NULL;
}
Example #10
0
static PyObject *
partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
    PyObject *func;
    partialobject *pto;

    if (PyTuple_GET_SIZE(args) < 1) {
        PyErr_SetString(PyExc_TypeError,
                        "type 'partial' takes at least one argument");
        return NULL;
    }

    func = PyTuple_GET_ITEM(args, 0);
    if (!PyCallable_Check(func)) {
        PyErr_SetString(PyExc_TypeError,
                        "the first argument must be callable");
        return NULL;
    }

    /* create partialobject structure */
    pto = (partialobject *)type->tp_alloc(type, 0);
    if (pto == NULL)
        return NULL;

    pto->fn = func;
    Py_INCREF(func);
    pto->args = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
    if (pto->args == NULL) {
        pto->kw = NULL;
        Py_DECREF(pto);
        return NULL;
    }
    if (kw != NULL) {
        pto->kw = PyDict_Copy(kw);
        if (pto->kw == NULL) {
            Py_DECREF(pto);
            return NULL;
        }
    } else {
        pto->kw = Py_None;
        Py_INCREF(Py_None);
    }

    pto->weakreflist = NULL;
    pto->dict = NULL;

    return (PyObject *)pto;
}
Example #11
0
static PyObject *
wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
{
	STACKLESS_GETARG();
	Py_ssize_t argc;
	PyObject *self, *func, *result;

	/* Make sure that the first argument is acceptable as 'self' */
	assert(PyTuple_Check(args));
	argc = PyTuple_GET_SIZE(args);
	if (argc < 1) {
		PyErr_Format(PyExc_TypeError,
			     "descriptor '%.300s' of '%.100s' "
			     "object needs an argument",
			     descr_name((PyDescrObject *)descr),
			     descr->d_type->tp_name);
		return NULL;
	}
	self = PyTuple_GET_ITEM(args, 0);
	if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
		PyErr_Format(PyExc_TypeError,
			     "descriptor '%.200s' "
			     "requires a '%.100s' object "
			     "but received a '%.100s'",
			     descr_name((PyDescrObject *)descr),
			     descr->d_type->tp_name,
			     self->ob_type->tp_name);
		return NULL;
	}

	func = PyWrapper_New((PyObject *)descr, self);
	if (func == NULL)
		return NULL;
	args = PyTuple_GetSlice(args, 1, argc);
	if (args == NULL) {
		Py_DECREF(func);
		return NULL;
	}
	STACKLESS_PROMOTE_ALL();
	result = PyEval_CallObjectWithKeywords(func, args, kwds);
	STACKLESS_ASSERT();
	Py_DECREF(args);
	Py_DECREF(func);
	return result;
}
Example #12
0
/* Returns a NEW reference to the callback/errback arg, and to the
 * cbackArgs, but a BORROWED reference to the keywords. In case of
 * error, no references are returned/touched */
static PyObject *extract_cback_args_kw(char *argname,
                                       PyObject *args, PyObject *kwargs,
                                       PyObject **cbackArgs,
                                       PyObject **cbackKeywords) {
    PyObject *cback;

    if (kwargs) {
        (*cbackKeywords) = kwargs;
    } else {
        (*cbackKeywords) = Py_None;
    }
    if (PyTuple_Size(args) > 0) {
        cback = PyTuple_GET_ITEM(args, 0);
        if (!cback) {
            return NULL;
        }
        (*cbackArgs) = PyTuple_GetSlice(args, 1, PyTuple_Size(args));
        if (!(*cbackArgs)) {
            return NULL;
        }
        Py_INCREF(cback);
    } else {
        cback = PyDict_GetItemString((*cbackKeywords), argname);
        if (!cback) {
            PyErr_Format(PyExc_TypeError,
                         "addCallback requires '%s' argument'", argname);
            return NULL;
        }
        (*cbackArgs) = Py_None;
        Py_INCREF(Py_None);

        /* "callback" in the keyword dict may be the only reference to
         * it, and we delete it from the dict, so we must own a
         * reference too */
        Py_INCREF(cback);

        if (PyDict_DelItemString((*cbackKeywords), argname) == -1) {
            Py_DECREF(cback);
            Py_DECREF(Py_None);
            return NULL;
        }
    }
    return cback;
}
Example #13
0
Element *GetElementFromObject(PyObject *obj)
{
    if (PyObject_HasAttrString(obj, (char*) "ptr")) {
        PyObject* ptr = PyObject_GetAttrString(obj, (char*) "ptr");
        long addr = PyLong_AsLong(ptr);
        Py_DECREF(ptr);
        
        return Id2Element(addr); //(Element*) addr;
    } else {
        // python code
        // NOTE: I think the only element that uses this code is a color
        // construct outside any graphic
        
        // do nothing if not a tuple
        // and check that header is int
        if (!PyTuple_Check(obj) ||
            PyTuple_GET_SIZE(obj) < 1 ||
            !PyInt_Check(PyTuple_GET_ITEM(obj, 0)))
            return NULL;
        
        // build element based on header
        int elmid = (int) PyInt_AsLong(PyTuple_GET_ITEM(obj, 0));

        Element *elm = g_elementFactory.Create(elmid);
        if (elm == NULL) {
            // invalid elmid, return error
            return NULL;
        }
        
        Scm code = Py2ScmTake(PyTuple_GetSlice(obj, 1, PyTuple_GET_SIZE(obj)));
        
        if (!elm->Build(elmid, code)) {
            delete elm;
            return NULL;
        }
        
        // return the built element
        return elm;
    }
}
static PyObject *
verifying_changed(verify *self, PyObject *ignored)
{
  PyObject *t, *ro;

  verifying_clear(self);

  t = PyObject_GetAttr(OBJECT(self), str_registry);
  if (t == NULL)
    return NULL;
  ro = PyObject_GetAttr(t, strro);
  Py_DECREF(t);
  if (ro == NULL)
    return NULL;

  t = PyObject_CallFunctionObjArgs(OBJECT(&PyTuple_Type), ro, NULL);
  Py_DECREF(ro);
  if (t == NULL)
    return NULL;

  ro = PyTuple_GetSlice(t, 1, PyTuple_GET_SIZE(t));
  Py_DECREF(t);
  if (ro == NULL)
    return NULL;

  self->_verify_generations = _generations_tuple(ro);
  if (self->_verify_generations == NULL)
    {
      Py_DECREF(ro);
      return NULL;
    }

  self->_verify_ro = ro;

  Py_INCREF(Py_None);
  return Py_None;
}
Example #15
0
// Register signal change callback
// First argument should be the signal handle
// Second argument is the function to call
// Remaining arguments and keyword arguments are to be passed to the callback
static PyObject *register_value_change_callback(PyObject *self, PyObject *args) //, PyObject *keywds)
{
    FENTER

    PyObject *fArgs;
    PyObject *function;
    gpi_sim_hdl sig_hdl;
    gpi_sim_hdl hdl;
    unsigned int edge;

    p_callback_data callback_data_p;

    Py_ssize_t numargs = PyTuple_Size(args);

    if (numargs < 3) {
        fprintf(stderr, "Attempt to register value change callback without enough arguments!\n");
        return NULL;
    }

    PyObject *pSihHdl = PyTuple_GetItem(args, 0);
    if (!gpi_sim_hdl_converter(pSihHdl, &sig_hdl)) {
        return NULL;
    }

    // Extract the callback function
    function = PyTuple_GetItem(args, 1);
    if (!PyCallable_Check(function)) {
        fprintf(stderr, "Attempt to register value change callback without passing a callable callback!\n");
        return NULL;
    }
    Py_INCREF(function);

    PyObject *pedge = PyTuple_GetItem(args, 2);
    edge = (unsigned int)PyLong_AsLong(pedge);

    // Remaining args for function
    fArgs = PyTuple_GetSlice(args, 3, numargs);   // New reference
    if (fArgs == NULL) {
        return NULL;
    }


    callback_data_p = (p_callback_data)malloc(sizeof(s_callback_data));
    if (callback_data_p == NULL) {
        return PyErr_NoMemory();
    }

    // Set up the user data (no more python API calls after this!)
    // Causes segfault?
    callback_data_p->_saved_thread_state = PyThreadState_Get();//PyThreadState_Get();
    callback_data_p->id_value = COCOTB_ACTIVE_ID;
    callback_data_p->function = function;
    callback_data_p->args = fArgs;
    callback_data_p->kwargs = NULL;

    hdl = gpi_register_value_change_callback((gpi_function_t)handle_gpi_callback,
                                             callback_data_p,
                                             sig_hdl,
                                             edge);

    // Check success
    PyObject *rv = PyLong_FromVoidPtr(hdl);
    FEXIT

    return rv;
}
Example #16
0
static PyObject *
partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
    PyObject *func, *pargs, *nargs, *pkw;
    partialobject *pto;

    if (PyTuple_GET_SIZE(args) < 1) {
        PyErr_SetString(PyExc_TypeError,
                        "type 'partial' takes at least one argument");
        return NULL;
    }

    pargs = pkw = NULL;
    func = PyTuple_GET_ITEM(args, 0);
    if (Py_TYPE(func) == &partial_type && type == &partial_type) {
        partialobject *part = (partialobject *)func;
        if (part->dict == NULL) {
            pargs = part->args;
            pkw = part->kw;
            func = part->fn;
            assert(PyTuple_Check(pargs));
            assert(PyDict_Check(pkw));
        }
    }
    if (!PyCallable_Check(func)) {
        PyErr_SetString(PyExc_TypeError,
                        "the first argument must be callable");
        return NULL;
    }

    /* create partialobject structure */
    pto = (partialobject *)type->tp_alloc(type, 0);
    if (pto == NULL)
        return NULL;

    pto->fn = func;
    Py_INCREF(func);

    nargs = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
    if (nargs == NULL) {
        Py_DECREF(pto);
        return NULL;
    }
    if (pargs == NULL || PyTuple_GET_SIZE(pargs) == 0) {
        pto->args = nargs;
        Py_INCREF(nargs);
    }
    else if (PyTuple_GET_SIZE(nargs) == 0) {
        pto->args = pargs;
        Py_INCREF(pargs);
    }
    else {
        pto->args = PySequence_Concat(pargs, nargs);
        if (pto->args == NULL) {
            Py_DECREF(nargs);
            Py_DECREF(pto);
            return NULL;
        }
        assert(PyTuple_Check(pto->args));
    }
    Py_DECREF(nargs);

    if (pkw == NULL || PyDict_GET_SIZE(pkw) == 0) {
        if (kw == NULL) {
            pto->kw = PyDict_New();
        }
        else {
            Py_INCREF(kw);
            pto->kw = kw;
        }
    }
    else {
        pto->kw = PyDict_Copy(pkw);
        if (kw != NULL && pto->kw != NULL) {
            if (PyDict_Merge(pto->kw, kw, 1) != 0) {
                Py_DECREF(pto);
                return NULL;
            }
        }
    }
    if (pto->kw == NULL) {
        Py_DECREF(pto);
        return NULL;
    }

    return (PyObject *)pto;
}
Example #17
0
/*
 * Invoke a single slot (Qt or Python) and return the result.
 */
PyObject *sip_api_invoke_slot(const sipSlot *slot, PyObject *sigargs)
{
    PyObject *sa, *oxtype, *oxvalue, *oxtb, *sfunc, *sref;

    /* Keep some compilers quiet. */
    oxtype = oxvalue = oxtb = NULL;

    /* Fan out Qt signals.  (Only PyQt3 will do this.) */
    if (slot->name != NULL && slot->name[0] != '\0')
    {
        assert(sipQtSupport->qt_emit_signal);

        if (sipQtSupport->qt_emit_signal(slot->pyobj, slot->name, sigargs) < 0)
            return NULL;

        Py_INCREF(Py_None);
        return Py_None;
    }

    /* Get the object to call, resolving any weak references. */
    if (slot->weakSlot == Py_True)
    {
        /*
         * The slot is guaranteed to be Ok because it has an extra reference or
         * is None.
         */
        sref = slot->pyobj;
        Py_INCREF(sref);
    }
    else if (slot -> weakSlot == NULL)
        sref = NULL;
    else if ((sref = PyWeakref_GetObject(slot -> weakSlot)) == NULL)
        return NULL;
    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);

        Py_INCREF(Py_None);
        return Py_None;
    }

    if (slot -> pyobj == NULL)
    {
        PyObject *self = (sref != NULL ? sref : slot->meth.mself);

        /*
         * If the receiver wraps a C++ object then ignore the call if it no
         * longer exists.
         */
        if (PyObject_TypeCheck(self, (PyTypeObject *)&sipSimpleWrapper_Type) &&
            sip_api_get_address((sipSimpleWrapper *)self) == NULL)
        {
            Py_XDECREF(sref);

            Py_INCREF(Py_None);
            return Py_None;
        }

#if PY_MAJOR_VERSION >= 3
        sfunc = PyMethod_New(slot->meth.mfunc, self);
#else
        sfunc = PyMethod_New(slot->meth.mfunc, self, slot->meth.mclass);
#endif

        if (sfunc == NULL)
        {
            Py_XDECREF(sref);
            return NULL;
        }
    }
    else if (slot -> name != NULL)
    {
        char *mname = slot -> name + 1;
        PyObject *self = (sref != NULL ? sref : slot->pyobj);

        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(sfunc);
            Py_XDECREF(sref);
            return NULL;
        }
    }
    else
    {
        sfunc = slot->pyobj;
        Py_INCREF(sfunc);
    }

    /*
     * 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(sfunc);
            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 resobj;
        }

        /* 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_DECREF(sfunc);
    Py_XDECREF(sref);

    Py_DECREF(sa);

    return NULL;
}
/* Can't simply connect "frame_done" signal like the others.  The handler
   is of type:  gint func (GdkPixbufLoader *loader,
			   GdkPixbufFrame  *frame,
			   gpointer         data)
   If you simply connect it from python it will pass in 'frame' as a
   CObject, and since it wasn't created with a 'destroy' handler you can't
   manipulate 'frame' within python code (program will silently exit).
   We need to get a hold of 'frame' first, convert it to a GtkObject and
   then pass it on to the user function in python.
*/
static void marshal_frame_done_cb (GtkObject *loader_ptr, 
				   gpointer func_args_tuple_ptr, 
				   guint nargs, GtkArg *args)
{
	/*FIXME I'm probably f*****g this up */
	PyObject *loader_python, *func_args_tuple_orig, *frame_python, *func;
	PyObject *func_args_tuple;
	PyObject *new_args, *result;
	GdkPixbufFrame *frame;
	int check;
		
	PyGtk_BlockThreads ();
	dbg ();

	frame = (GdkPixbufFrame *) GTK_VALUE_POINTER(args[0]);
	func_args_tuple = (PyObject *) func_args_tuple_ptr;
	Py_XINCREF (func_args_tuple);

	
	//loader_python = PyGdkPixbuf_LoaderNew ((GdkPixbufLoader *) loader_ptr);
	loader_python = PyGtk_New (loader_ptr);
	if (loader_python == NULL)
	{	dprint ("couldn't make loader_python\n");
		goto error;
	}

	frame_python = PyGdkPixbuf_FrameNew (frame);
	if (frame_python == NULL)
	{	dprint ("couldn't make frame_python\n");
		goto error;
	}

	func = PyTuple_GetItem (func_args_tuple, 0);
	if (func == NULL)
	{	dprint ("couldn't get func from tuple\n");
		goto error;
	}

	check = PyTuple_SetItem (func_args_tuple, 1, loader_python);
	if (check != 0)
	{	dprint ("func_args_tuple[1] = loader_python failed\n");
		goto error;
	}

	check = PyTuple_SetItem (func_args_tuple, 2, frame_python);
	if (check != 0)
	{	dprint ("func_args_tuple[2] = frame_python failed\n");
		goto error;
	}

	/*FIXME are the tuple items "stolen" references??? */
	new_args = PyTuple_GetSlice (func_args_tuple, 1, 
			 	PyTuple_Size(func_args_tuple));
	if (new_args == NULL)
	{	dprint ("new_args = func_args_tuple[1:] failed\n");
		goto error;
	}

	result = PyObject_CallObject (func, new_args);
	if (result == NULL)
	{	Py_XDECREF (new_args);
		dprint ("func(new_args) returned NULL\n");
		goto error;
	}

	GtkRet_FromPyObject (&args[nargs], result);
	Py_DECREF (result);
	PyGtk_UnblockThreads ();
	return;
	
error:
	Py_XDECREF (func_args_tuple);
	if (PyGtk_FatalExceptions)
		gtk_main_quit ();
	else
	  {	PyErr_Print ();
		PyErr_Clear ();
	  }
	PyGtk_UnblockThreads ();
	return;
}
Example #19
0
/**
 * _py_args_combine_and_check_length:
 * @cache: PyGICallableCache
 * @py_args: the tuple of positional arguments.
 * @py_kwargs: the dict of keyword arguments to be merged with py_args.
 *
 * Returns: New value reference to the combined py_args and py_kwargs.
 */
static PyObject *
_py_args_combine_and_check_length (PyGICallableCache *cache,
                                   PyObject    *py_args,
                                   PyObject    *py_kwargs)
{
    PyObject *combined_py_args = NULL;
    Py_ssize_t n_py_args, n_py_kwargs, i;
    guint n_expected_args = cache->n_py_args;
    GSList *l;

    n_py_args = PyTuple_GET_SIZE (py_args);
    if (py_kwargs == NULL)
        n_py_kwargs = 0;
    else
        n_py_kwargs = PyDict_Size (py_kwargs);

    /* Fast path, we already have the exact number of args and not kwargs. */
    if (n_py_kwargs == 0 && n_py_args == n_expected_args && cache->user_data_varargs_index < 0) {
        Py_INCREF (py_args);
        return py_args;
    }

    if (cache->user_data_varargs_index < 0 && n_expected_args < n_py_args) {
        char *full_name = pygi_callable_cache_get_full_name (cache);
        PyErr_Format (PyExc_TypeError,
                      "%.200s() takes exactly %d %sargument%s (%zd given)",
                      full_name,
                      n_expected_args,
                      n_py_kwargs > 0 ? "non-keyword " : "",
                      n_expected_args == 1 ? "" : "s",
                      n_py_args);
        g_free (full_name);
        return NULL;
    }

    if (cache->user_data_varargs_index >= 0 && n_py_kwargs > 0 && n_expected_args < n_py_args) {
        char *full_name = pygi_callable_cache_get_full_name (cache);
        PyErr_Format (PyExc_TypeError,
                      "%.200s() cannot use variable user data arguments with keyword arguments",
                      full_name);
        g_free (full_name);
        return NULL;
    }

    if (n_py_kwargs > 0 && !_check_for_unexpected_kwargs (cache,
                                                          cache->arg_name_hash,
                                                          py_kwargs)) {
        return NULL;
    }

    /* will hold arguments from both py_args and py_kwargs
     * when they are combined into a single tuple */
    combined_py_args = PyTuple_New (n_expected_args);

    for (i = 0, l = cache->arg_name_list; i < n_expected_args && l; i++, l = l->next) {
        PyObject *py_arg_item = NULL;
        PyObject *kw_arg_item = NULL;
        const gchar *arg_name = l->data;
        int arg_cache_index = -1;
        gboolean is_varargs_user_data = FALSE;

        if (arg_name != NULL)
            arg_cache_index = GPOINTER_TO_INT (g_hash_table_lookup (cache->arg_name_hash, arg_name));

        is_varargs_user_data = cache->user_data_varargs_index >= 0 &&
                                arg_cache_index == cache->user_data_varargs_index;

        if (n_py_kwargs > 0 && arg_name != NULL) {
            /* NULL means this argument has no keyword name */
            /* ex. the first argument to a method or constructor */
            kw_arg_item = PyDict_GetItemString (py_kwargs, arg_name);
        }

        /* use a bounded retrieval of the original input */
        if (i < n_py_args)
            py_arg_item = PyTuple_GET_ITEM (py_args, i);

        if (kw_arg_item == NULL && py_arg_item != NULL) {
            if (is_varargs_user_data) {
                /* For tail end user_data varargs, pull a slice off and we are done. */
                PyObject *user_data = PyTuple_GetSlice (py_args, i, PY_SSIZE_T_MAX);
                PyTuple_SET_ITEM (combined_py_args, i, user_data);
                return combined_py_args;
            } else {
                Py_INCREF (py_arg_item);
                PyTuple_SET_ITEM (combined_py_args, i, py_arg_item);
            }
        } else if (kw_arg_item != NULL && py_arg_item == NULL) {
            if (is_varargs_user_data) {
                /* Special case where user_data is passed as a keyword argument (user_data=foo)
                 * Wrap the value in a tuple to represent variable args for marshaling later on.
                 */
                PyObject *user_data = Py_BuildValue("(O)", kw_arg_item, NULL);
                PyTuple_SET_ITEM (combined_py_args, i, user_data);
            } else {
                Py_INCREF (kw_arg_item);
                PyTuple_SET_ITEM (combined_py_args, i, kw_arg_item);
            }

        } else if (kw_arg_item == NULL && py_arg_item == NULL) {
            if (is_varargs_user_data) {
                /* For varargs user_data, pass an empty tuple when nothing is given. */
                PyTuple_SET_ITEM (combined_py_args, i, PyTuple_New (0));
            } else if (arg_cache_index >= 0 && _pygi_callable_cache_get_arg (cache, arg_cache_index)->has_default) {
                /* If the argument supports a default, use a place holder in the
                 * argument tuple, this will be checked later during marshaling.
                 */
                Py_INCREF (_PyGIDefaultArgPlaceholder);
                PyTuple_SET_ITEM (combined_py_args, i, _PyGIDefaultArgPlaceholder);
            } else {
                char *full_name = pygi_callable_cache_get_full_name (cache);
                PyErr_Format (PyExc_TypeError,
                              "%.200s() takes exactly %d %sargument%s (%zd given)",
                              full_name,
                              n_expected_args,
                              n_py_kwargs > 0 ? "non-keyword " : "",
                              n_expected_args == 1 ? "" : "s",
                              n_py_args);
                g_free (full_name);

                Py_DECREF (combined_py_args);
                return NULL;
            }
        } else if (kw_arg_item != NULL && py_arg_item != NULL) {
            char *full_name = pygi_callable_cache_get_full_name (cache);
            PyErr_Format (PyExc_TypeError,
                          "%.200s() got multiple values for keyword argument '%.200s'",
                          full_name,
                          arg_name);

            Py_DECREF (combined_py_args);
            g_free (full_name);
            return NULL;
        }
    }

    return combined_py_args;
}
Example #20
0
// Call a single slot and return the result.
PyObject *PyQtSlot::call(PyObject *callable, PyObject *args) const
{
    PyObject *sa, *oxtype, *oxvalue, *oxtb;

    // Keep some compilers quiet.
    oxtype = oxvalue = oxtb = 0;

    // 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 = args;
    Py_INCREF(sa);

    for (;;)
    {
        PyObject *nsa, *xtype, *xvalue, *xtb, *res;

        if ((res = PyEval_CallObject(callable, sa)) != NULL)
        {
            // Remove any previous exception.

            if (sa != args)
            {
                Py_XDECREF(oxtype);
                Py_XDECREF(oxvalue);
                Py_XDECREF(oxtb);
                PyErr_Clear();
            }

            Py_DECREF(sa);

            return res;
        }

        // 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 ||
            PyTuple_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)
            {
                if (sa != args)
                {
                    Py_XDECREF(oxtype);
                    Py_XDECREF(oxvalue);
                    Py_XDECREF(oxtb);
                }

                PyErr_Restore(xtype,xvalue,xtb);
            }
            else if (sa == args)
            {
                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 == args)
        {
            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_Size(sa) - 1)) == NULL)
        {
            // Tidy up.
            Py_XDECREF(oxtype);
            Py_XDECREF(oxvalue);
            Py_XDECREF(oxtb);

            break;
        }

        Py_DECREF(sa);
        sa = nsa;
    }

    Py_DECREF(sa);

    return 0;
}