Using the C API when Embedding — SIP v4.19.25 Reference Guide

# 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.