/** * 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; } }
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; }
/** 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; }
// 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; }
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; }
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; }
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; }
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; }
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; }
/* 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; }
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; }
// 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; }
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; }
/* * 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; }
/** * _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; }
// 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; }