# Using the C API: Assorted topics

The tutorial walked you through creating a C API extension module, but left many areas unexplained. This document looks at several concepts that you’ll need to learn in order to write more complex extensions.

## Errors and Exceptions

파이썬 인터프리터 전체에서 중요한 규칙은 다음과 같습니다: 함수가 실패하면 예외 조건을 설정하고 에러값(보통 `-1`이나 `NULL` 포인터)을 반환해야 합니다. 예외 정보는 인터프리터의 스레드 상태의 세 멤버에 저장됩니다. 예외가 발생하지 않았으면 이들은 `NULL`입니다. 그렇지 않으면, `sys.exc_info()`가 반환하는 파이썬 튜플 멤버의 C 동등 물입니다. 이들은 예외 형, 예외 인스턴스, 트레이스백 객체입니다. 에러가 어떻게 전달되는지 이해하기 위해서는 이들에 대해 아는 것이 중요합니다.

파이썬 API는 다양한 형의 예외를 설정하기 위한 여러 함수를 정의합니다.

가장 일반적인 것은 `PyErr_SetString()`입니다. 인자는 예외 객체와 C 문자열입니다. 예외 객체는 보통 `PyExc_ZeroDivisionError`와 같은 미리 정의된 객체입니다. C 문자열은 에러의 원인을 나타내며 파이썬 문자열 객체로 변환되어 예외의 “연관된 값”으로 저장됩니다.

또 다른 유용한 함수는 `PyErr_SetFromErrno()`입니다. 이 함수는 예외 인자만 취하고 전역 변수 `errno`를 검사하여 관련 값을 구성합니다. 가장 일반적인 함수는 `PyErr_SetObject()`이며, 예외와 관련 값인 두 개의 객체 인자를 취합니다. 이러한 함수들에 전달되는 객체를 `Py_INCREF()` 할 필요는 없습니다.

`PyErr_Occurred()`로 예외가 설정되어 있는지 비 파괴적으로 검사할 수 있습니다. 현재 예외 객체나 예외가 발생하지 않았으면 `NULL`을 반환합니다. 반환 값에서 알 수 있어야 해서 일반적으로 함수 호출에서 에러가 발생했는지 확인하기 위해 `PyErr_Occurred()`를 호출할 필요는 없습니다.

다른 함수 g를 호출하는 함수 f가 g의 실패를 감지할 때, f 자체가 에러값(보통 `NULL`이나 `-1`)을 반환해야 합니다. `PyErr_*` 함수 중 하나를 호출하지 않아야 합니다 — g에 의해 이미 호출되었습니다. 그러면 f의 호출자도 역시 `PyErr_*` 호출 없이, 자신의 호출자에게 에러 표시를 반환하고, 이런 식으로 계속된다고 가정합니다 — 에러를 가장 먼저 감지한 함수에 의해 에러의 가장 자세한 원인이 이미 보고되었습니다. 일단 에러가 파이썬 인터프리터의 메인 루프에 도달하면, 현재 실행 중인 파이썬 코드를 중단하고 파이썬 프로그래머가 지정한 예외 처리기를 찾으려고 시도합니다.

(모듈이 실제로 다른 `PyErr_*` 함수를 호출하여 더 자세한 에러 메시지를 표시할 수 있는 상황이 있습니다. 그럴 때는 그렇게 하는 것이 좋습니다. 그러나, 일반적인 규칙으로 이는 필요하지 않고, 에러가 발생하는 원인에 관한 정보를 잃어버리게 합니다: 대부분의 연산은 다양한 이유로 실패할 수 있습니다.)

실패한 함수 호출로 설정된 예외를 무시하려면, `PyErr_Clear()`를 호출하여 예외 조건을 명시적으로 지워야 합니다. C 코드가 `PyErr_Clear()`를 호출해야 하는 유일한 때는 에러를 인터프리터에 전달하지 않고 스스로 완전히 처리하려고 하는 경우입니다 (아마 다른 것을 시도하거나, 아무것도 잘못되지 않은 척해서).

모든 실패한 `malloc()` 호출은 예외로 전환되어야 합니다 — `malloc()`(또는 `realloc()`)의 직접 호출자는 스스로 `PyErr_NoMemory()`를 호출하고 실패 표시기를 반환해야 합니다. 모든 객체 생성 함수(예를 들어, `PyLong_FromLong()`)는 이미 이 작업을 수행하므로, 이 주의는 `malloc()`을 직접 호출하는 호출자에게만 해당합니다.

또한 `PyArg_ParseTuple()`과 그 친구들의 중요한 예외를 제외하고, 정수 상태를 반환하는 함수는 유닉스 시스템 호출처럼 일반적으로 성공 시 양수 값이나 0을 반환하고, 실패 시 `-1`을 반환합니다.

마지막으로, 에러 표시기를 반환할 때 (이미 만든 객체를 `Py_XDECREF()`나 `Py_DECREF()`를 호출하여) 가비지를 정리하십시오!

어떤 예외를 발생시킬지는 전적으로 여러분의 것입니다. 모든 내장 파이썬 예외에 해당하는 사전 선언된 C 객체(가령 `PyExc_ZeroDivisionError`)가 있는데, 직접 사용할 수 있습니다. 물론, 예외를 현명하게 선택해야 합니다 — 파일을 열 수 없음을 뜻하는 데 `PyExc_TypeError`를 사용하지 마십시오 (아마도 `PyExc_OSError`여야 합니다). 인자 목록에 문제가 있으면, `PyArg_ParseTuple()` 함수는 일반적으로 `PyExc_TypeError`를 발생시킵니다. 값이 특정 범위 내에 있어야 하거나 다른 조건을 만족해야 하는 인자가 있으면, `PyExc_ValueError`가 적합합니다.

You can also define a new exception that is unique to your module. The simplest way to do this is to declare a static global object variable at the beginning of the file:

    static PyObject *SpamError = NULL;

and initialize it by calling `PyErr_NewException()` in the module’s `Py_mod_exec` function (`spam_module_exec()`):

    SpamError = PyErr_NewException("spam.error", NULL, NULL);

Since `SpamError` is a global variable, it will be overwritten every time the module is reinitialized, when the `Py_mod_exec` function is called.

For now, let’s avoid the issue: we will block repeated initialization by raising an `ImportError`:

    static PyObject *SpamError = NULL;

    static int
    spam_module_exec(PyObject *m)
    {
        if (SpamError != NULL) {
            PyErr_SetString(PyExc_ImportError,
                            "cannot initialize spam module more than once");
            return -1;
        }
        SpamError = PyErr_NewException("spam.error", NULL, NULL);
        if (PyModule_AddObjectRef(m, "SpamError", SpamError) < 0) {
            return -1;
        }

        return 0;
    }

    static PyModuleDef_Slot spam_module_slots[] = {
        {Py_mod_exec, spam_module_exec},
        {0, NULL}
    };

    static struct PyModuleDef spam_module = {
        .m_base = PyModuleDef_HEAD_INIT,
        .m_name = "spam",
        .m_size = 0,  // non-negative
        .m_slots = spam_module_slots,
    };

    PyMODINIT_FUNC
    PyInit_spam(void)
    {
        return PyModuleDef_Init(&spam_module);
    }

예외 객체의 파이썬 이름은 `spam.error`임에 유의하십시오. `PyErr_NewException()` 함수는 (`NULL` 대신 다른 클래스가 전달되지 않는 한) 베이스 클래스가 (내장 예외에서 설명된) `Exception`인 클래스를 만들 수 있습니다.

`SpamError` 변수는 새로 만들어진 예외 클래스에 대한 참조를 보유함에도 유의하십시오; 이것은 의도적입니다! 외부 코드에 의해 예외가 모듈에서 제거될 수 있기 때문에, 클래스가 버려져서 `SpamError`가 매달린(dangling) 포인터가 되지 않도록 하려면, 클래스에 대한 참조를 소유할 필요가 있습니다. 매달린 포인터가 되면, 예외를 발생시키는 C 코드가 코어 덤프나 다른 의도하지 않은 부작용을 일으킬 수 있습니다.

For now, the `Py_DECREF()` call to remove this reference is missing. Even when the Python interpreter shuts down, the global `SpamError` variable will not be garbage-collected. It will “leak”. We did, however, ensure that this will happen at most once per process.

이 샘플의 뒷부분에서 `PyMODINIT_FUNC`를 함수 반환형으로 사용하는 것에 관해 설명합니다.

다음과 같이 `PyErr_SetString()`을 호출하여 확장 모듈에서 `spam.error` 예외를 발생시킬 수 있습니다:

    static PyObject *
    spam_system(PyObject *self, PyObject *args)
    {
        const char *command;
        int sts;

        if (!PyArg_ParseTuple(args, "s", &command))
            return NULL;
        sts = system(command);
        if (sts < 0) {
            PyErr_SetString(SpamError, "System command failed");
            return NULL;
        }
        return PyLong_FromLong(sts);
    }

## Embedding an extension

If you want to make your module a permanent part of the Python interpreter, you will have to change the configuration setup and rebuild the interpreter. On Unix, place your file (`spammodule.c` for example) in the `Modules/` directory of an unpacked source distribution, add a line to the file `Modules/Setup.local` describing your file:

    spam spammodule.o

그리고 최상위 디렉터리에서 make를 실행하여 인터프리터를 다시 빌드하십시오. `Modules/` 서브 디렉터리에서 make를 실행할 수도 있지만, 먼저 ‘make Makefile’을 실행하여 `Makefile`을 다시 빌드해야 합니다. (이것은 `Setup` 파일을 변경할 때마다 필요합니다.)

모듈에 링크할 추가 라이브러리가 필요하면, 이것도 구성 파일의 줄에 나열될 수 있습니다, 예를 들어:

    spam spammodule.o -lX11

## C에서 파이썬 함수 호출하기

The tutorial concentrated on making C functions callable from Python. The reverse is also useful: calling Python functions from C. This is especially the case for libraries that support so-called “callback” functions. If a C interface makes use of callbacks, the equivalent Python often needs to provide a callback mechanism to the Python programmer; the implementation will require calling the Python callback functions from a C callback. Other uses are also imaginable.

다행히, 파이썬 인터프리터는 재귀적으로 쉽게 호출되며, 파이썬 함수를 호출하는 표준 인터페이스가 있습니다. (특정 문자열을 입력으로 파이썬 파서를 호출하는 방법에 대해서는 다루지 않겠습니다 — 관심이 있다면, 파이썬 소스 코드에서 `Modules/main.c`의 `-c` 명령 줄 옵션 구현을 살펴보십시오.)

파이썬 함수를 호출하기는 쉽습니다. 먼저, 파이썬 프로그램은 어떻게 든 여러분에게 파이썬 함수 객체를 전달해야 합니다. 이를 위해 함수(또는 다른 인터페이스)를 제공해야 합니다. 이 함수가 호출될 때, 전역 변수(또는 여러분이 보기에 적절한 곳 어디에나)에 파이썬 함수 객체에 대한 포인터를 저장하십시오 (`Py_INCREF()`해야 하는 것에 주의하십시오!). 예를 들어, 다음 함수는 모듈 정의의 일부일 수 있습니다:

    static PyObject *my_callback = NULL;

    static PyObject *
    my_set_callback(PyObject *dummy, PyObject *args)
    {
        PyObject *result = NULL;
        PyObject *temp;

        if (PyArg_ParseTuple(args, "O:set_callback", &temp)) {
            if (!PyCallable_Check(temp)) {
                PyErr_SetString(PyExc_TypeError, "parameter must be callable");
                return NULL;
            }
            Py_XINCREF(temp);         /* 새 콜백에 대한 참조를 추가합니다 */
            Py_XDECREF(my_callback);  /* 이전 콜백을 제거합니다 */
            my_callback = temp;       /* 새 콜백을 기억합니다 */
            /* "None" 을 반환하는 보일러 플레이트 */
            Py_INCREF(Py_None);
            result = Py_None;
        }
        return result;
    }

This function must be registered with the interpreter using the `METH_VARARGS` flag in `PyMethodDef.ml_flags`. The `PyArg_ParseTuple()` function and its arguments are documented in section 확장 함수에서 매개 변수 추출하기.

매크로 `Py_XINCREF()`와 `Py_XDECREF()`는 객체의 참조 횟수를 증가/감소시키며 `NULL` 포인터가 있을 때 안전합니다 (그러나 이 문맥에서 temp는 `NULL`이 아님에 유의하십시오). 섹션 참조 횟수에 이에 대한 자세한 정보가 있습니다.

나중에, 함수를 호출할 때, C 함수 `PyObject_CallObject()`를 호출합니다. 이 함수에는 두 개의 인자가 있는데, 모두 임의의 파이썬 객체에 대한 포인터입니다: 파이썬 함수와 인자 목록. 인자 목록은 항상 길이가 인자의 수인 튜플 객체여야 합니다. 인자 없이 파이썬 함수를 호출하려면, `NULL`이나 빈 튜플을 전달하십시오; 하나의 인자로 호출하려면, 단 항목 튜플을 전달하십시오. `Py_BuildValue()`는 포맷 문자열이 괄호 사이에 0개 이상의 포맷 코드로 구성되었을 때 튜플을 반환합니다. 예를 들면:

    int arg;
    PyObject *arglist;
    PyObject *result;
    ...
    arg = 123;
    ...
    /* 콜백을 호출할 시간입니다 */
    arglist = Py_BuildValue("(i)", arg);
    result = PyObject_CallObject(my_callback, arglist);
    Py_DECREF(arglist);

`PyObject_CallObject()`는 파이썬 객체 포인터를 반환합니다: 이것은 파이썬 함수의 반환 값입니다. `PyObject_CallObject()`는 인자와 관련하여 “참조 횟수 중립적”입니다. 이 예에서는 `PyObject_CallObject()` 호출 직후 `Py_DECREF()`되는 인자 목록으로 사용할 새 튜플이 만들어졌습니다.

`PyObject_CallObject()`의 반환 값은 “새것”입니다: 완전히 새로운 객체이거나 참조 횟수가 증가한 기존 객체입니다. 따라서, 전역 변수에 저장하려는 것이 아닌 한, 설사 (특히!) 그 값에 관심이 없더라도 결과를 `Py_DECREF()`해야 합니다.

그러나, 이 작업을 수행하기 전에 반환 값이 `NULL`이 아닌지 확인해야 합니다. 그렇다면, 파이썬 함수는 예외를 발생 시켜 종료한 것입니다. `PyObject_CallObject()`라는 C 코드가 파이썬에서 호출되었다면 이제 파이썬 호출자에게 에러 표시를 반환하여, 인터프리터가 스택 트레이스를 인쇄하거나 호출하는 파이썬 코드가 예외를 처리할 수 있도록 합니다. 이것이 불가능하거나 바람직하지 않으면, `PyErr_Clear()`를 호출하여 예외를 지워야 합니다. 예를 들면:

    if (result == NULL)
        return NULL; /* 에러를 돌려줍니다 */
    ...use result...
    Py_DECREF(result);

파이썬 콜백 함수에 대해 원하는 인터페이스에 따라, `PyObject_CallObject()`에 인자 목록을 제공해야 할 수도 있습니다. 때에 따라 인자 목록은 콜백 함수를 지정한 같은 인터페이스를 통해 파이썬 프로그램에서 제공됩니다. 그런 다음 함수 객체와 같은 방식으로 저장하고 사용할 수 있습니다. 다른 경우에는, 인자 목록으로 전달할 새 튜플을 구성해야 할 수도 있습니다. 이렇게 하는 가장 간단한 방법은 `Py_BuildValue()`를 호출하는 것입니다. 예를 들어, 정수 이벤트 코드를 전달하려면, 다음 코드를 사용할 수 있습니다:

    PyObject *arglist;
    ...
    arglist = Py_BuildValue("(l)", eventcode);
    result = PyObject_CallObject(my_callback, arglist);
    Py_DECREF(arglist);
    if (result == NULL)
        return NULL; /* 에러를 돌려줍니다 */
    /* 여기서 아마도 result를 사용합니다 */
    Py_DECREF(result);

호출 직후, 에러 점검 전에 `Py_DECREF(arglist)`의 배치에 유의하십시오! 또한 엄격하게 말하면 이 코드가 완전하지 않음에도 유의하십시오: `Py_BuildValue()`에 메모리가 부족할 수 있어서 확인해야 합니다.

인자와 키워드 인자를 지원하는 `PyObject_Call()`을 사용하여 키워드 인자가 있는 함수를 호출할 수도 있습니다. 위의 예에서와같이, `Py_BuildValue()`를 사용하여 딕셔너리를 구성합니다.

    PyObject *dict;
    ...
    dict = Py_BuildValue("{s:i}", "name", val);
    result = PyObject_Call(my_callback, NULL, dict);
    Py_DECREF(dict);
    if (result == NULL)
        return NULL; /* 에러를 돌려줍니다 */
    /* 여기서 아마도 result를 사용합니다 */
    Py_DECREF(result);

## 확장 함수에서 매개 변수 추출하기

The tutorial uses a “`METH_O`” function, which is limited to a single Python argument. If you want more, you can use `METH_VARARGS` instead. With this flag, the C function will receive a `tuple` of arguments instead of a single object.

For unpacking the tuple, CPython provides the `PyArg_ParseTuple()` function, declared as follows:

    int PyArg_ParseTuple(PyObject *arg, const char *format, ...);

arg 인자는 파이썬에서 C 함수로 전달되는 인자 목록이 포함된 튜플 객체여야 합니다. format 인자는 포맷 문자열이어야 하며, 문법은 파이썬/C API 레퍼런스 매뉴얼의 인자 구문 분석과 값 구축에 설명되어 있습니다. 나머지 인자는 포맷 문자열에 의해 형이 결정되는 변수의 주소여야 합니다.

For example, to receive a single Python `str` object and turn it into a C buffer, you would use `"s"` as the format string:

    const char *command;
    if (!PyArg_ParseTuple(args, "s", &command)) {
        return NULL;
    }

If an error is detected in the argument list, `PyArg_ParseTuple()` returns `NULL` (the error indicator for functions returning object pointers); your function may return `NULL`, relying on the exception set by `PyArg_ParseTuple()`.

`PyArg_ParseTuple()`은 파이썬 인자가 요구되는 형인지 확인하지만, 호출에 전달된 C 변수 주소의 유효성을 확인할 수는 없습니다: 실수를 하면, 코드가 충돌하거나 적어도 메모리의 임의 비트를 덮어씁니다. 그러니 조심하십시오!

호출자에게 제공되는 모든 파이썬 객체 참조는 빌려온(borrowed) 참조임에 유의하십시오; 참조 횟수를 줄이지 마십시오!

몇 가지 예제 호출:

    #include <Python.h>

    int ok;
    int i, j;
    long k, l;
    const char *s;
    Py_ssize_t size;

    ok = PyArg_ParseTuple(args, ""); /* 인자가 없습니다 */
        /* 파이썬 호출: f() */

    ok = PyArg_ParseTuple(args, "s", &s); /* 문자열 */
        /* 가능한 파이썬 호출: f('whoops!') */

    ok = PyArg_ParseTuple(args, "lls", &k, &l, &s); /* 두 개의 long과 문자열 */
        /* 가능한 파이썬 호출: f(1, 2, 'three') */

    ok = PyArg_ParseTuple(args, "(ii)s#", &i, &j, &s, &size);
        /* int 쌍과 문자열, 문자열의 크기도 반환됩니다 */
        /* 가능한 파이썬 호출: f((1, 2), 'three') */

    {
        const char *file;
        const char *mode = "r";
        int bufsize = 0;
        ok = PyArg_ParseTuple(args, "s|si", &file, &mode, &bufsize);
        /* 문자열, 그리고 선택적으로 또 다른 문자열과 정수 */
        /* 가능한 파이썬 호출:
           f('spam')
           f('spam', 'w')
           f('spam', 'wb', 100000) */
    }

    {
        int left, top, right, bottom, h, v;
        ok = PyArg_ParseTuple(args, "((ii)(ii))(ii)",
                 &left, &top, &right, &bottom, &h, &v);
        /* 직사각형과 점 */
        /* 가능한 파이썬 호출:
           f(((0, 0), (400, 300)), (10, 10)) */
    }

    {
        Py_complex c;
        ok = PyArg_ParseTuple(args, "D:myfunction", &c);
        /* 복소수, 에러를 위한 함수 이름도 제공합니다 */
        /* 가능한 파이썬 호출: myfunction(1+2j) */
    }

## 확장 함수를 위한 키워드 매개 변수

If you also want your function to accept keyword arguments, use the `METH_KEYWORDS` flag in combination with `METH_VARARGS`. (`METH_KEYWORDS` can also be used with other flags; see its documentation for the allowed combinations.)

In this case, the C function should accept a third `PyObject *` parameter which will be a dictionary of keywords. Use `PyArg_ParseTupleAndKeywords()` to parse the arguments to such a function.

`PyArg_ParseTupleAndKeywords()` 함수는 다음과 같이 선언됩니다:

    int PyArg_ParseTupleAndKeywords(PyObject *arg, PyObject *kwdict,
                                    const char *format, char * const *kwlist, ...);

arg와 format 매개 변수는 `PyArg_ParseTuple()` 함수와 동일합니다. kwdict 매개 변수는 파이썬 런타임에서 세 번째 매개 변수로 수신된 키워드 딕셔너리입니다. kwlist 매개 변수는 매개 변수를 식별하는 문자열의 `NULL` 종료 목록입니다; 이름은 왼쪽에서 오른쪽으로 format의 형 정보와 일치합니다. 성공하면, `PyArg_ParseTupleAndKeywords()`는 참을 반환하고, 그렇지 않으면 거짓을 반환하고 적절한 예외를 발생시킵니다.

참고

키워드 인자를 사용할 때 중첩된 튜플을 구문분석할 수 없습니다! kwlist에 없는 키워드 매개 변수가 전달되면 `TypeError`를 발생시킵니다.

다음은 Geoff Philbrick (philbrick@hks.com) 의 예제를 기반으로 한, 키워드를 사용하는 예제 모듈입니다:

    #define PY_SSIZE_T_CLEAN
    #include <Python.h>

    static PyObject *
    keywdarg_parrot(PyObject *self, PyObject *args, PyObject *keywds)
    {
        int voltage;
        const char *state = "a stiff";
        const char *action = "voom";
        const char *type = "Norwegian Blue";

        static char *kwlist[] = {"voltage", "state", "action", "type", NULL};

        if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|sss", kwlist,
                                         &voltage, &state, &action, &type))
            return NULL;

        printf("-- This parrot wouldn't %s if you put %i Volts through it.\n",
               action, voltage);
        printf("-- Lovely plumage, the %s -- It's %s!\n", type, state);

        Py_RETURN_NONE;
    }

    static PyMethodDef keywdarg_methods[] = {
        /* The cast of the function is necessary since PyCFunction values
         * only take two PyObject* parameters, and keywdarg_parrot() takes
         * three.
         */
        {"parrot", (PyCFunction)(void(*)(void))keywdarg_parrot, METH_VARARGS | METH_KEYWORDS,
         "Print a lovely skit to standard output."},
        {NULL, NULL, 0, NULL}   /* sentinel */
    };

## 임의의 값을 구축하기

이 함수는 `PyArg_ParseTuple()`의 반대입니다. 다음과 같이 선언됩니다:

    PyObject *Py_BuildValue(const char *format, ...);

`PyArg_ParseTuple()`에서 인식되는 것과 유사한 포맷 단위 집합을 인식하지만, 인자(함수의 출력이 아니라 입력입니다)는 포인터가 아니라 그냥 값이어야 합니다. 파이썬에서 호출한 C 함수에서 반환하기에 적합한 새 파이썬 객체를 반환합니다.

`PyArg_ParseTuple()`과의 한 가지 차이점: 후자는 첫 번째 인자가 튜플이어야 하지만 (파이썬 인자 목록은 항상 내부적으로 튜플로 표현되기 때문입니다), `Py_BuildValue()`는 항상 튜플을 빌드하지는 않습니다. 포맷 문자열에 둘 이상의 포맷 단위가 포함된 경우에만 튜플을 빌드합니다. 포맷 문자열이 비어 있으면 `None`을 반환합니다; 정확히 하나의 포맷 단위를 포함하면, 그것이 무엇이건 해당 포맷 단위가 기술하는 객체를 반환합니다. 크기가 0이나 1인 튜플을 강제로 반환하도록 하려면, 포맷 문자열을 괄호로 묶으십시오.

예제 (왼쪽은 호출이고, 오른쪽은 결과 파이썬 값입니다):

    Py_BuildValue("")                        None
    Py_BuildValue("i", 123)                  123
    Py_BuildValue("iii", 123, 456, 789)      (123, 456, 789)
    Py_BuildValue("s", "hello")              'hello'
    Py_BuildValue("y", "hello")              b'hello'
    Py_BuildValue("ss", "hello", "world")    ('hello', 'world')
    Py_BuildValue("s#", "hello", 4)          'hell'
    Py_BuildValue("y#", "hello", 4)          b'hell'
    Py_BuildValue("()")                      ()
    Py_BuildValue("(i)", 123)                (123,)
    Py_BuildValue("(ii)", 123, 456)          (123, 456)
    Py_BuildValue("(i,i)", 123, 456)         (123, 456)
    Py_BuildValue("[i,i]", 123, 456)         [123, 456]
    Py_BuildValue("{s:i,s:i}",
                  "abc", 123, "def", 456)    {'abc': 123, 'def': 456}
    Py_BuildValue("((ii)(ii)) (ii)",
                  1, 2, 3, 4, 5, 6)          (((1, 2), (3, 4)), (5, 6))

## 참조 횟수

C나 C++ 와 같은 언어에서, 힙에서 메모리의 동적 할당과 할당 해제하는 것은 프로그래머가 담당합니다. C에서는, `malloc()`과 `free()` 함수를 사용하여 이 작업을 수행합니다. C++에서는, 연산자 `new`와 `delete`는 본질적으로 같은 의미로 사용되며 우리는 뒤따르는 논의를 C의 경우로 제한하겠습니다.

`malloc()`으로 할당된 모든 메모리 블록은 `free()`를 정확히 한 번 호출하여 사용 가능한 메모리 풀로 반환되어야 합니다. 적시에 `free()`를 호출하는 것이 중요합니다. 블록의 주소를 잊어버렸지만, `free()`를 호출하지 않으면 프로그램이 종료될 때까지 블록을 차지하는 메모리를 재사용할 수 없습니다. 이것을 메모리 누수(memory leak)라고 합니다. 반면에, 프로그램이 블록에 대해 `free()`를 호출한 다음 블록을 계속 사용하면, 다른 `malloc()` 호출을 통해 블록을 재사용할 때 충돌이 발생합니다. 이것을 해제된 메모리 사용하기(using freed memory)라고 합니다. 초기화되지 않은 데이터를 참조하는 것과 같은 나쁜 결과를 초래합니다 — 코어 덤프, 잘못된 결과, 미스테리한 충돌.

메모리 누수의 일반적인 원인은 코드를 통한 비정상적인 경로입니다. 예를 들어, 함수는 메모리 블록을 할당하고, 어떤 계산을 한 다음, 블록을 다시 해제할 수 있습니다. 이제 함수에 대한 요구 사항이 변경되어 에러 조건을 감지하는 계산에 대한 검사를 추가하고 함수가 조기에 반환할 수 있도록 합니다. 이 조기 탈출을 수행할 때, 특히 나중에 코드에 추가될 때, 할당된 메모리 블록을 해제하는 것을 잊어버리기 쉽습니다. 이러한 누수는 일단 만들어지면 종종 오랫동안 탐지되지 않습니다: 에러 탈출은 전체 호출의 작은 부분에서만 이루어지며, 대부분의 최신 시스템에는 많은 가상 메모리가 있어서, 누수 하는 함수를 자주 사용하는 오래 실행되는 프로세스에서만 누수가 나타납니다. 따라서, 이런 종류의 에러를 코딩 규칙이나 전략을 통해 누수가 발생하지 않도록 하는 것이 중요합니다.

파이썬은 `malloc()`과 `free()`를 많이 사용하기 때문에, 메모리 누수와 해제된 메모리 사용을 피하는 전략이 필요합니다. 선택된 방법을 참조 횟수 세기(reference counting)라고 합니다. 원리는 간단합니다: 모든 객체에는 카운터를 포함합니다, 카운터는 객체에 대한 참조가 어딘가에 저장될 때 증가하고, 참조가 삭제될 때 감소합니다. 카운터가 0에 도달하면, 객체에 대한 마지막 참조가 삭제된 것이고 객체가 해제됩니다.

대체 전략을 자동 가비지 수집(automatic garbage collection)이라고 합니다. (때로는, 참조 횟수 세기도 가비지 수집 전략이라고 해서, 두 가지를 구별하기 위해 “자동”을 붙였습니다.) 자동 가비지 수집의 가장 큰 장점은 사용자가 `free()`를 명시적으로 호출할 필요가 없다는 것입니다. (또 다른 주장된 이점은 속도나 메모리 사용량의 개선이지만 — 이것은 견고한 사실이 아닙니다.) 단점은 C의 경우 참조 횟수 세기는 이식성 있게 구현할 수 있지만 (함수 `malloc()`과 `free()`를 사용할 수 있는 한 — 이는 C 표준이 보장합니다), 실제로 이식성 있는 자동 가비지 수집기가 없다는 것입니다. 언젠가 C를 위해 충분히 이식성 있는 자동 가비지 수집기를 사용할 수 있을 것입니다. 그때까지, 우리는 참조 횟수와 함께 살아야 할 것입니다.

파이썬은 전통적인 참조 횟수 세기 구현을 사용하지만, 참조 순환을 감지하는 순환 감지기도 제공합니다. 이를 통해 응용 프로그램은 직접적이거나 간접적인 순환 참조를 만드는 것(이것이 참조 횟수만 사용하여 구현된 가비지 수집의 약점입니다)에 대해 걱정하지 않아도 됩니다. 참조 순환은 (어쩌면 간접적으로) 자신에 대한 참조를 포함하는 객체로 구성되어서, 순환의 각 객체는 0이 아닌 참조 횟수를 갖습니다. 일반적인 참조 횟수 세기 구현에서는 순환 자체에 대한 추가 참조가 없더라도 참조 순환의 객체에 속하는 메모리나 순환에 속한 객체에서 참조된 메모리를 회수할 수 없습니다.

The cycle detector is able to detect garbage cycles and can reclaim them. The `gc` module exposes a way to run the detector (the `collect()` function), as well as configuration interfaces and the ability to disable the detector at runtime.

### 파이썬에서 참조 횟수 세기

참조 횟수의 증가와 감소를 처리하는 두 개의 매크로 `Py_INCREF(x)`와 `Py_DECREF(x)`가 있습니다. `Py_DECREF()`는 횟수가 0에 도달하면 객체를 해제하기도 합니다. 유연성을 위해, `free()`를 직접 호출하지 않습니다 — 대신, 객체의 형 객체(type object)에 있는 함수 포인터를 통해 호출합니다. 이 목적(및 기타)을 위해 모든 객체에는 해당 형 객체에 대한 포인터도 포함됩니다.

이제 큰 질문이 남습니다: 언제 `Py_INCREF(x)`와 `Py_DECREF(x)`를 사용합니까? 먼저 몇 가지 용어를 소개하겠습니다. 아무도 객체를 “소유(owns)”하지 않습니다ㅣ 그러나, 객체에 대한 참조를 소유(own a reference)할 수 있습니다. 객체의 참조 횟수는 이제 이 객체에 대한 참조를 소유한 수로 정의됩니다. 참조 소유자는 더는 참조가 필요하지 않을 때 `Py_DECREF()`를 호출해야 합니다. 참조의 소유권을 양도할 수 있습니다. 소유한 참조를 처분하는 세 가지 방법이 있습니다: 전달, 저장 및 `Py_DECREF()` 호출. 소유한 참조를 처분하지 않으면 메모리 누수가 발생합니다.

It is also possible to borrow [1] a reference to an object. The borrower of a reference should not call `Py_DECREF()`. The borrower must not hold on to the object longer than the owner from which it was borrowed. Using a borrowed reference after the owner has disposed of it risks using freed memory and should be avoided completely [2].

참조 소유에 비교할 때 빌리기의 이점은 코드를 통한 가능한 모든 경로에서 참조를 처리할 필요가 없다는 것입니다 — 즉, 빌려온 참조를 사용하면 조기 종료 시에 누수의 위험이 없습니다. 소유하는 것에 비해 빌리는 것의 단점은, 겉보기에는 올바른 코드지만, 빌려준 소유자가 실제로는 참조를 처분한 후에 빌린 참조가 사용될 수 있는 미묘한 상황이 있다는 것입니다.

빌린 참조는 `Py_INCREF()`를 호출하여 소유한 참조로 변경할 수 있습니다. 이는 참조를 빌려온 소유자의 상태에 영향을 미치지 않습니다 — 새로운 소유된 참조를 만들고, 완전한 소유자 책임을 부여합니다 (이전 소유자뿐만 아니라, 새 소유자는 참조를 올바르게 처분해야 합니다).

### 소유권 규칙

객체 참조가 함수 안팎으로 전달될 때마다, 소유권이 참조와 함께 전달되는지 그렇지 않은지는 함수 인터페이스 명세의 일부입니다.

객체에 대한 참조를 반환하는 대부분의 함수는 참조와 함께 소유권을 전달합니다. 특히, `PyLong_FromLong()`이나 `Py_BuildValue()`와 같은 새 객체를 만드는 기능을 가진 모든 함수는 소유권을 수신자에게 전달합니다. 객체가 실제로 새 객체가 아니더라도, 여전히 해당 객체에 대한 새 참조의 소유권을 받습니다. 예를 들어, `PyLong_FromLong()`은 흔히 사용되는 값의 캐시를 유지하고 캐시 된 항목에 대한 참조를 반환할 수 있습니다.

다른 객체에서 객체를 추출하는 많은 함수도 참조와 함께 소유권을 전달합니다, 예를 들어 `PyObject_GetAttrString()`. 그러나 몇 가지 일반적인 루틴이 예외이기 때문에 그림이 명확하지 않습니다: `PyTuple_GetItem()`, `PyList_GetItem()`, `PyDict_GetItem()` 및 `PyDict_GetItemString()`은 모두 튜플, 리스트 또는 딕셔너리에서 빌린 참조를 반환합니다.

`PyImport_AddModule()` 함수도 실제는 반환하는 객체를 만들 수 있지만 빌린 참조를 반환합니다: 객체에 대한 소유한 참조가 `sys.modules`에 저장되어 있기 때문에 가능합니다.

객체 참조를 다른 함수에 전달할 때, 일반적으로, 함수는 여러분으로부터 참조를 빌립니다 — 참조를 저장해야 하면, `Py_INCREF()`를 사용하여 독립 소유자가 됩니다. 이 규칙에는 두 가지 중요한 예외가 있습니다: `PyTuple_SetItem()`과 `PyList_SetItem()`. 이 함수들은 전달된 항목에 대한 소유권을 취합니다 — 설사 실패하더라도! (`PyDict_SetItem()`과 그 친구들은 소유권을 취하지 않습니다 — 이들은 “정상” 입니다.)

C 함수가 파이썬에서 호출될 때, 호출자로부터 온 인자에 대한 참조를 빌립니다. 호출자는 객체에 대한 참조를 소유하기 때문에, 빌린 참조의 수명은 함수가 반환될 때까지 보장됩니다. 이러한 빌린 참조를 저장하거나 전달해야 할 때만, `Py_INCREF()`를 호출하여 소유한 참조로 만들어야 합니다.

파이썬에서 호출된 C 함수에서 반환된 객체 참조는 소유한 참조여야 합니다 — 소유권은 함수에서 호출자로 전달됩니다.

### 살얼음

겉보기에 무해한 빌린 참조의 사용이 문제를 일으킬 수 있는 몇 가지 상황이 있습니다. 이것들은 모두 참조의 소유자가 참조를 처분하도록 할 수 있는 인터프리터의 묵시적 호출과 관련이 있습니다.

가장 먼저 알아야 할 가장 중요한 경우는 리스트 항목에 대한 참조를 빌리는 동안 관련이 없는 객체에서 `Py_DECREF()`를 사용하는 것입니다. 예를 들어:

    void
    bug(PyObject *list)
    {
        PyObject *item = PyList_GetItem(list, 0);

        PyList_SetItem(list, 1, PyLong_FromLong(0L));
        PyObject_Print(item, stdout, 0); /* BUG! */
    }

이 함수는 먼저 `list[0]`에 대한 참조를 빌린 다음, `list[1]`을 값 `0`으로 바꾸고, 마지막으로 빌린 참조를 인쇄합니다. 무해해 보이지요? 하지만 그렇지 않습니다!

Let’s follow the control flow into `PyList_SetItem()`. The list owns references to all its items, so when item 1 is replaced, it has to dispose of the original item 1. Now let’s suppose the original item 1 was an instance of a user-defined class, and let’s further suppose that the class defined a `__del__()` method. If this class instance has a reference count of 1, disposing of it will call its `__del__()` method. Internally, `PyList_SetItem()` calls `Py_DECREF()` on the replaced item, which invokes replaced item’s corresponding `tp_dealloc` function. During deallocation, `tp_dealloc` calls `tp_finalize`, which is mapped to the `__del__()` method for class instances (see PEP 442). This entire sequence happens synchronously within the `PyList_SetItem()` call.

파이썬으로 작성되었기 때문에, `__del__()` 메서드는 임의의 파이썬 코드를 실행할 수 있습니다. 그것이 `bug()`에서 `item`에 대한 참조를 무효로 하는 작업을 수행할 수 있을까요? 물론입니다! `bug()`에 전달된 리스트가 `__del__()` 메서드에서 액세스 가능하다고 가정하면, `del list[0]`의 효과를 주는 문장을 실행할 수 있으며, 이것이 해당 객체에 대한 마지막 참조라고 가정하면, 그것과 연관된 메모리를 해제하고, 그래서 `item`을 무효로 합니다.

문제의 원인을 알고 나면, 해결 방법은 쉽습니다: 일시적으로 참조 횟수를 늘리십시오. 올바른 버전의 함수는 다음과 같습니다:

    void
    no_bug(PyObject *list)
    {
        PyObject *item = PyList_GetItem(list, 0);

        Py_INCREF(item);
        PyList_SetItem(list, 1, PyLong_FromLong(0L));
        PyObject_Print(item, stdout, 0);
        Py_DECREF(item);
    }

이것은 실제 이야기입니다. 이전 버전의 파이썬에는 이 버그의 변형이 포함되어 있으며 누군가 `__del__()` 메서드가 실패하는 이유를 알아내기 위해 C 디버거에서 상당한 시간을 보냈습니다…

The second case of problems with a borrowed reference is a variant involving threads. Normally, multiple threads in the Python interpreter can’t get in each other’s way, because there is a global lock protecting Python’s entire object space. However, it is possible to temporarily release this lock using the macro `Py_BEGIN_ALLOW_THREADS`, and to re-acquire it using `Py_END_ALLOW_THREADS`. This is common around blocking I/O calls, to let other threads use the processor while waiting for the I/O to complete. Obviously, the following function has the same problem as the previous one:

    void
    bug(PyObject *list)
    {
        PyObject *item = PyList_GetItem(list, 0);
        Py_BEGIN_ALLOW_THREADS
        ...some blocking I/O call...
        Py_END_ALLOW_THREADS
        PyObject_Print(item, stdout, 0); /* 버그! */
    }

### NULL 포인터

일반적으로, 객체 참조를 인자로 취하는 함수는 `NULL` 포인터를 전달할 것으로 기대하지 않으며, 그렇게 하면 코어를 덤프합니다 (또는 이후의 코어 덤프를 유발합니다). 객체 참조를 반환하는 함수는 일반적으로 예외가 발생했음을 나타내기 위해서만 `NULL`을 반환합니다. `NULL` 인자를 검사하지 않는 이유는 함수들이 종종 자신이 받은 객체를 다른 함수에 전달하기 때문입니다 — 각 함수가 `NULL`을 검사한다면, 중복 검사가 많이 발생하고 코드가 더 느리게 실행됩니다.

`NULL`일 수 있는 포인터가 수신될 때 “소스”에서만 `NULL`을 검사하는 것이 좋습니다, 예를 들어, `malloc()`이나 예외를 발생시킬 수 있는 함수에서.

매크로 `Py_INCREF()`와 `Py_DECREF()`는 `NULL` 포인터를 검사하지 않습니다 — 하지만, 그들의 변형 `Py_XINCREF()`와 `Py_XDECREF()`는 확인합니다.

특정 객체 형을 확인하기 위한 매크로(`Pytype_Check()`)는 `NULL` 포인터를 확인하지 않습니다 — 다시, 여러 기대하는 형에 대해 객체를 검사하기 위해 연속해서 이들을 여러 번 호출하는 코드가 많아서, 중복 검사가 생성됩니다. `NULL` 검사를 하는 변형은 없습니다.

The C function calling mechanism guarantees that the argument list passed to C functions (`args` in the examples) is never `NULL` — in fact it guarantees that it is always a tuple [3].

`NULL` 포인터를 파이썬 사용자에게 “빠져나가게” 만드는 것은 심각한 에러입니다.

## C++로 확장 작성하기

C++로 확장 모듈을 작성할 수 있습니다. 일부 제한 사항이 적용됩니다. 메인 프로그램(파이썬 인터프리터)이 C 컴파일러로 컴파일되고 링크되면, 생성자가 있는 전역이나 정적(static) 객체를 사용할 수 없습니다. 메인 프로그램이 C++ 컴파일러로 링크된 경우에는 문제가 되지 않습니다. 파이썬 인터프리터가 호출할 함수(특히, 모듈 초기화 함수)는 `extern "C"`를 사용하여 선언해야 합니다. `extern "C" {...}`로 파이썬 헤더 파일을 묶을 필요는 없습니다 — `__cplusplus` 기호가 정의되면 (모든 최신 C++ 컴파일러가 이 기호를 정의합니다) 이미 이 형식을 사용합니다.

## 확장 모듈을 위한 C API 제공하기

많은 확장 모듈은 단지 파이썬에서 사용할 새로운 함수와 형을 제공하지만, 때로 확장 모듈의 코드가 다른 확장 모듈에 유용할 수 있습니다. 예를 들어, 확장 모듈은 순서 없는 리스트처럼 작동하는 “컬렉션” 형을 구현할 수 있습니다. 표준 파이썬 리스트 형에 확장 모듈이 리스트를 만들고 조작할 수 있게 하는 C API가 있는 것처럼, 이 새로운 컬렉션 형에는 다른 확장 모듈에서 직접 조작할 수 있는 C 함수 집합이 있어야 합니다.

첫눈에 이것은 쉬운 것처럼 보입니다; 단지 함수를 작성하고 (물론 `static`을 선언하지 않고), 적절한 헤더 파일을 제공하고, C API를 설명합니다. 사실 이것은 모든 확장 모듈이 항상 파이썬 인터프리터와 정적으로 링크되어 있다면 작동합니다. 그러나 모듈을 공유 라이브러리로 사용하면, 한 모듈에 정의된 기호가 다른 모듈에서 보이지 않을 수 있습니다. 가시성의 세부 사항은 운영 체제에 따라 다릅니다; 어떤 시스템은 파이썬 인터프리터와 모든 확장 모듈에 하나의 전역 이름 공간을 사용하는 반면 (예를 들어 윈도우), 다른 시스템은 모듈 링크 시점에 임포트 되는 기호의 목록을 명시적으로 요구하거나 (AIX가 하나의 예입니다), 여러 전략 중 선택할 수 있도록 합니다 (대부분의 유닉스). 또한 기호가 전역적으로 보이더라도, 호출하려는 함수를 가진 모듈이 아직 로드되지 않았을 수 있습니다!

Portability therefore requires not to make any assumptions about symbol visibility. This means that all symbols in extension modules should be declared `static`, except for the module’s initialization function, in order to avoid name clashes with other extension modules. And it means that symbols that should be accessible from other extension modules must be exported in a different way.

파이썬은 한 확장 모듈에서 다른 확장 모듈로 C 수준 정보(포인터)를 전달하는 특별한 메커니즘을 제공합니다: 캡슐(Capsule). 캡슐은 포인터(void*)를 저장하는 파이썬 데이터형입니다. 캡슐은 C API를 통해서만 만들고 액세스할 수 있지만, 다른 파이썬 객체처럼 전달할 수 있습니다. 특히, 확장 모듈의 이름 공간에서 이름에 대입할 수 있습니다. 다른 확장 모듈은 이 모듈을 임포트 해서, 이 이름의 값을 가져온 다음, 캡슐에서 포인터를 가져올 수 있습니다.

확장 모듈의 C API를 노출하는 데 캡슐을 사용하는 방법에는 여러 가지가 있습니다. 각 함수가 자신만의 캡슐을 얻거나, 모든 C API 포인터가 저장된 배열의 주소를 캡슐로 게시할 수 있습니다. 그리고 포인터를 저장하고 꺼내는 다양한 작업은 코드를 제공하는 모듈과 클라이언트 모듈 간에 여러 방식으로 분산될 수 있습니다.

어떤 방법을 선택하든, 캡슐 이름을 올바르게 지정하는 것이 중요합니다. `PyCapsule_New()` 함수는 name 매개 변수(const char*)를 취합니다; `NULL` name을 전달할 수는 있지만, 이름을 지정하도록 강력히 권고합니다. 적절하게 이름 붙인 캡슐은 어느 정도의 실행 시간 형 안전성을 제공합니다; 하나의 이름 없는 캡슐을 다른 캡슐과 구별할 수 있는 적절한 방법은 없습니다.

특히, C API를 공개하는 데 사용되는 캡슐에는 다음 규칙에 따라 이름을 지정해야 합니다:

    modulename.attributename

편의 함수 `PyCapsule_Import()`를 사용하면 캡슐을 통해 제공된 C API를 쉽게 로드 할 수 있지만, 캡슐 이름이 이 규칙과 일치할 때만 그렇습니다. 이 동작은 C API 사용자에게 자신이 로드 한 캡슐에 올바른 C API가 포함되어 있다는 확신을 줍니다.

다음 예제는 대부분의 부담을 내보내는 모듈의 작성자에게 주는 방식을 보여주는데, 일반적으로 사용되는 라이브러리 모듈에 적합합니다. 캡슐의 값이 되는 void 포인터의 배열에 모든 C API 포인터(이 예에서는 하나뿐입니다!)를 저장합니다. 모듈에 해당하는 헤더 파일은 모듈을 임포트 하고 C API 포인터를 가져오는 매크로를 제공합니다; 클라이언트 모듈은 C API에 액세스하기 전에 이 매크로를 호출하기만 하면 됩니다.

The exporting module is a modification of the `spam` module from the tutorial. The function `spam.system()` does not call the C library function `system()` directly, but a function `PySpam_System()`, which would of course do something more complicated in reality (such as adding “spam” to every command). This function `PySpam_System()` is also exported to other extension modules.

함수 `PySpam_System()`은 평범한 C 함수이며, 다른 모든 것과 같이 `static`으로 선언되었습니다:

    static int
    PySpam_System(const char *command)
    {
        return system(command);
    }

`spam_system()` 함수는 사소하게 수정됩니다:

    static PyObject *
    spam_system(PyObject *self, PyObject *args)
    {
        const char *command;
        int sts;

        if (!PyArg_ParseTuple(args, "s", &command))
            return NULL;
        sts = PySpam_System(command);
        return PyLong_FromLong(sts);
    }

모듈의 시작 부분에서, 다음 줄 바로 다음에

    #include <Python.h>

다음 두 줄을 더 추가해야 합니다:

    #define SPAM_MODULE
    #include "spammodule.h"

The `#define` is used to tell the header file that it is being included in the exporting module, not a client module. Finally, the module’s `mod_exec` function must take care of initializing the C API pointer array:

    static int
    spam_module_exec(PyObject *m)
    {
        static void *PySpam_API[PySpam_API_pointers];
        PyObject *c_api_object;

        /* Initialize the C API pointer array */
        PySpam_API[PySpam_System_NUM] = (void *)PySpam_System;

        /* Create a Capsule containing the API pointer array's address */
        c_api_object = PyCapsule_New((void *)PySpam_API, "spam._C_API", NULL);

        if (PyModule_Add(m, "_C_API", c_api_object) < 0) {
            return -1;
        }

        return 0;
    }

`PySpam_API`는 `static`으로 선언됩니다; 그렇지 않으면 `PyInit_spam()`이 종료할 때 포인터 배열이 사라집니다!

작업 대부분은 헤더 파일 `spammodule.h`에 있으며, 다음과 같습니다:

    #ifndef Py_SPAMMODULE_H
    #define Py_SPAMMODULE_H
    #ifdef __cplusplus
    extern "C" {
    #endif

    /* spammodule 의 헤더 파일 */

    /* C API functions */
    #define PySpam_System_NUM 0
    #define PySpam_System_RETURN int
    #define PySpam_System_PROTO (const char *command)

    /* C API 포인터의 총수 */
    #define PySpam_API_pointers 1

    #ifdef SPAM_MODULE
    /* 이 섹션은 spammodule.c를 컴파일할 때 사용됩니다 */

    static PySpam_System_RETURN PySpam_System PySpam_System_PROTO;

    #else
    /* 이 섹션은 spammodule의 API를 사용하는 모듈에서 사용됩니다 */

    static void **PySpam_API;

    #define PySpam_System \
     (*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])

    /* 에러 시 -1, 성공 시 0을 반환합니다.
     * PyCapsule_Import는 에러가 있으면 예외를 설정합니다.
     */
    static int
    import_spam(void)
    {
        PySpam_API = (void **)PyCapsule_Import("spam._C_API", 0);
        return (PySpam_API != NULL) ? 0 : -1;
    }

    #endif

    #ifdef __cplusplus
    }
    #endif

    #endif /* !defined(Py_SPAMMODULE_H) */

All that a client module must do in order to have access to the function `PySpam_System()` is to call the function (or rather macro) `import_spam()` in its `mod_exec` function:

    static int
    client_module_exec(PyObject *m)
    {
        if (import_spam() < 0) {
            return -1;
        }
        /* additional initialization can happen here */
        return 0;
    }

이 방법의 주요 단점은 파일 `spammodule.h`가 다소 복잡하다는 것입니다. 그러나, 기본 구조는 내보내는 함수마다 같아서, 한 번만 학습하면 됩니다.

마지막으로 캡슐은 추가 기능을 제공하며, 특히 캡슐에 저장된 포인터의 메모리 할당과 할당 해제에 유용합니다. 세부 사항은 파이썬/C API 레퍼런스 매뉴얼의 캡슐 섹션과 캡슐 구현(파이썬 소스 코드 배포의 `Include/pycapsule.h`와 `Objects/pycapsule.c` 파일)에 설명되어 있습니다.

각주

[1]

참조 “빌리기(borrowing)” 은유는 완전히 올바르지 않습니다: 소유자는 여전히 참조 사본을 가지고 있습니다.

[2]

참조 횟수가 1 이상인지 확인하는 것은 작동하지 않습니다 — 참조 횟수 자체가 해제된 메모리에 있을 수 있어서 다른 객체에 재사용될 수 있습니다!

[3]

“오래된” 스타일 호출 규칙을 사용할 때 이러한 보장은 유지되지 않습니다 — 이것은 여전히 기존 코드에서 많이 발견됩니다.