Ejemplo n.º 1
0
/*
 * Implement strdup() using sip_api_malloc().
 */
static char *sipStrdup(const char *s)
{
    char *d;

    if ((d = (char *)sip_api_malloc(strlen(s) + 1)) != NULL)
        strcpy(d,s);

    return d;
}
Ejemplo n.º 2
0
/*
 * Add a new API to the global list returning a negative value on error.
 */
static int add_api(const char *api, int version_nr)
{
    apiVersionDef *avd;

    if ((avd = sip_api_malloc(sizeof (apiVersionDef))) == NULL)
        return -1;

    avd->api_name = api;
    avd->version_nr = version_nr;
    avd->next = api_versions;

    api_versions = avd;

    return 0;
}
Ejemplo n.º 3
0
/*
 * Set the version number for an API.
 */
PyObject *sipSetAPI(PyObject *self, PyObject *args)
{
    const char *api;
    int version_nr;
    const apiVersionDef *avd;

    if (!PyArg_ParseTuple(args, "si:setapi", &api, &version_nr))
        return NULL;

    if (version_nr < 1)
    {
        PyErr_Format(PyExc_ValueError,
                "API version numbers must be greater or equal to 1, not %d",
                version_nr);
        return NULL;
    }

    if ((avd = find_api(api)) == NULL)
    {
        char *api_copy;

        /* Make a deep copy of the name. */
        if ((api_copy = sip_api_malloc(strlen(api) + 1)) == NULL)
            return NULL;

        strcpy(api_copy, api);

        if (add_api(api_copy, version_nr) < 0)
            return NULL;
    }
    else if (avd->version_nr != version_nr)
    {
        PyErr_Format(PyExc_ValueError,
                "API '%s' has already been set to version %d", api,
                avd->version_nr);
        return NULL;
    }

    Py_INCREF(Py_None);
    return Py_None;
}
Ejemplo n.º 4
0
/*
 * Return the thread data for the current thread, allocating it if necessary,
 * or NULL if there was an error.
 */
static threadDef *currentThreadDef(int auto_alloc)
{
    threadDef *thread, *empty = NULL;
    long ident = PyThread_get_thread_ident();

    /* See if we already know about the thread. */
    for (thread = threads; thread != NULL; thread = thread->next)
    {
        if (thread->thr_ident == ident)
            return thread;

        if (thread->thr_ident == 0)
            empty = thread;
    }

    if (!auto_alloc)
    {
        /* This is not an error. */
        return NULL;
    }

    if (empty != NULL)
    {
        /* Use an empty entry in the list. */
        thread = empty;
    }
    else if ((thread = sip_api_malloc(sizeof (threadDef))) == NULL)
    {
        return NULL;
    }
    else
    {
        thread->next = threads;
        threads = thread;
    }

    thread->thr_ident = ident;
    thread->pending.cpp = NULL;

    return thread;
}
Ejemplo n.º 5
0
Archivo: threads.c Proyecto: Kanma/sip
/*
 * This is called from a newly created thread to initialise some thread local
 * storage.
 */
void sip_api_start_thread(void)
{
#ifdef WITH_THREAD
    threadDef *thread;

    /* Save the thread ID.  First, find an empty slot in the list. */
    for (thread = threads; thread != NULL; thread = thread->next)
        if (thread->thr_ident == 0)
            break;

    if (thread == NULL)
    {
        thread = sip_api_malloc(sizeof (threadDef));
        thread->next = threads;
        threads = thread;
    }

    if (thread != NULL)
    {
        thread->thr_ident = PyThread_get_thread_ident();
        thread->pending.cpp = NULL;
    }
#endif
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
/*
 * Initialise the the API for a module and return a negative value on error.
 */
int sipInitAPI(sipExportedModuleDef *em, PyObject *mod_dict)
{
    int *apis, i;
    sipVersionedFunctionDef *vf;
    sipTypeDef **tdp;

    /* See if the module defines any APIs. */
    if ((apis = em->em_versions) != NULL)
    {
        while (apis[0] >= 0)
        {
            /*
             * See if it is an API definition rather than a range
             * definition.
             */
            if (apis[2] < 0)
            {
                const char *api_name;
                const apiVersionDef *avd;

                api_name = sipNameFromPool(em, apis[0]);

                /* Use the default version if not already set explicitly. */
                if ((avd = find_api(api_name)) == NULL)
                    if (add_api(api_name, apis[1]) < 0)
                        return -1;
            }

            apis += 3;
        }
    }

    /* Add any versioned global functions to the module dictionary. */
    if ((vf = em->em_versioned_functions) != NULL)
    {
        while (vf->vf_name >= 0)
        {
            if (sipIsRangeEnabled(em, vf->vf_api_range))
            {
                const char *func_name = sipNameFromPool(em, vf->vf_name);
                PyMethodDef *pmd;
                PyObject *py_func;

                if ((pmd = sip_api_malloc(sizeof (PyMethodDef))) == NULL)
                    return -1;

                pmd->ml_name = SIP_MLNAME_CAST(func_name);
                pmd->ml_meth = vf->vf_function;
                pmd->ml_flags = vf->vf_flags;
                pmd->ml_doc = vf->vf_docstring;

                if ((py_func = PyCFunction_New(pmd, NULL)) == NULL)
                    return -1;

                if (PyDict_SetItemString(mod_dict, func_name, py_func) < 0)
                {
                    Py_DECREF(py_func);
                    return -1;
                }

                Py_DECREF(py_func);
            }

            ++vf;
        }
    }

    /* Update the types table according to any version information. */
    for (tdp = em->em_types, i = 0; i < em->em_nrtypes; ++i, ++tdp)
    {
        sipTypeDef *td;

        if ((td = *tdp) != NULL && td->td_version >= 0)
        {
            do
            {
                if (sipIsRangeEnabled(em, td->td_version))
                {
                    /* Update the type with the enabled version. */
                    *tdp = td;
                    break;
                }
            }
            while ((td = td->td_next_version) != NULL);

            /*
             * If there is no enabled version then stub the disabled version
             * so that we don't lose the name from the (sorted) types table.
             */
            if (td == NULL)
                sipTypeSetStub(*tdp);
        }
    }

    return 0;
}