Using the C API when EmbeddingΒΆ

The C API is intended to be called from handwritten code in SIP generated modules. However it is also often necessary to call it from C or C++ applications that embed the Python interpreter and need to pass C or C++ instances between the application and the interpreter.

The API is exported by the SIP module as a sipAPIDef data structure containing a set of function pointers. The data structure is defined in the SIP header file sip.h. When using Python v2.7, or Python v3.1 or later the data structure is wrapped as a Python PyCapsule object. When using other versions of Python the data structure is wrapped as a Python PyCObject object. It is referenced by the name _C_API in the SIP module dictionary.

Each member of the data structure is a pointer to one of the functions of the SIP API. The name of the member can be derived from the function name by replacing the sip prefix with api and converting each word in the name to lower case and preceding it with an underscore. For example:

sipExportSymbol becomes api_export_symbol

sipWrapperCheck becomes api_wrapper_check

Note that the type objects that SIP generates for a wrapped module (see Generated Type Structures, Generated Named Enum Type Objects and Generated Exception Objects) cannot be refered to directly and must be obtained using the sipFindType() function. Of course, the corresponding modules must already have been imported into the interpreter.

The following code fragment shows how to get a pointer to the sipAPIDef data structure:

#include <sip.h>

const sipAPIDef *get_sip_api()
{
#if defined(SIP_USE_PYCAPSULE)
    return (const sipAPIDef *)PyCapsule_Import("sip._C_API", 0);
#else
    PyObject *sip_module;
    PyObject *sip_module_dict;
    PyObject *c_api;

    /* Import the SIP module. */
    sip_module = PyImport_ImportModule("sip");

    if (sip_module == NULL)
        return NULL;

    /* Get the module's dictionary. */
    sip_module_dict = PyModule_GetDict(sip_module);

    /* Get the "_C_API" attribute. */
    c_api = PyDict_GetItemString(sip_module_dict, "_C_API");

    if (c_api == NULL)
        return NULL;

    /* Sanity check that it is the right type. */
    if (!PyCObject_Check(c_api))
        return NULL;

    /* Get the actual pointer from the object. */
    return (const sipAPIDef *)PyCObject_AsVoidPtr(c_api);
#endif
}

The use of SIP_USE_PYCAPSULE means that code will run under all versions of Python.