0Pricing
Python Academy · 강의

Python C 확장 모듈 작성

Python/C API를 사용해 간단한 .so 확장을 만듭니다.

Python C 확장 모듈 작성은(는) CoddyKit의 무료 Python Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Python Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Python Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

C 확장 기능의 구조

최소한의 C 확장 기능에는 메서드 함수, 메서드 표, 모듈 정의 구조체와 PyInit_ 진입점이 필요합니다.

// myext.c skeleton
#include <Python.h>

static PyObject* say_hello(PyObject* self, PyObject* args) {
    Py_RETURN_NONE;
}

static PyMethodDef methods[] = {
    {"say_hello", say_hello, METH_NOARGS, "Print hello"},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef module = {
    PyModuleDef_HEAD_INIT, "myext", NULL, -1, methods
};

PyMODINIT_FUNC PyInit_myext(void) {
    return PyModule_Create(&module);
}

인수 구문 분석

PyArg_ParseTuple(args, "ii", &a, &b)는 Python 인수를 C 변수로 구문 분석합니다. 형식 코드는 i=int, d=double, s=char*, O=PyObject*입니다.

static PyObject* add(PyObject* self, PyObject* args) {
    int a, b;
    if (!PyArg_ParseTuple(args, "ii", &a, &b))
        return NULL;
    return PyLong_FromLong(a + b);
}

값 반환

다음 함수를 사용하여 Python 반환 값을 생성합니다: PyLong_FromLong, PyFloat_FromDouble, PyUnicode_FromString, Py_BuildValue.

// Return a Python tuple (int, float)
static PyObject* stats(PyObject* self, PyObject* args) {
    int n = 10;
    double avg = 5.0;
    return Py_BuildValue("(id)", n, avg);
    // Py_BuildValue format: i=int d=double s=str
}

참조 횟수 관리

모든 PyObject*에는 참조 횟수가 있습니다. Py_INCREF/Py_DECREF를 신중하게 사용하십시오. C 함수의 반환 값은 호출자에게 소유권을 부여합니다(참조 소유권 이전).

static PyObject* make_list(PyObject* self, PyObject* args) {
    PyObject* lst = PyList_New(3);
    for (int i = 0; i < 3; i++) {
        // PyList_SET_ITEM steals the reference:
        PyList_SET_ITEM(lst, i, PyLong_FromLong(i));
    }
    return lst;   // caller owns the list
}

예외 발생시키기

PyErr_SetString(PyExc_ValueError, "msg")를 사용하여 C에서 Python 예외를 발생시킨 다음 NULL을 반환합니다.

static PyObject* safe_div(PyObject* self, PyObject* args) {
    int a, b;
    if (!PyArg_ParseTuple(args, "ii", &a, &b)) return NULL;
    if (b == 0) {
        PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
        return NULL;
    }
    return PyLong_FromLong(a / b);
}

C 확장 기능용 setup.py

setuptools.Extension을 사용하여 C 소스 파일을 선언합니다. python setup.py build_ext --inplace로 빌드합니다.

# setup.py
from setuptools import setup, Extension

setup(
    name="myext",
    ext_modules=[
        Extension(
            "myext",
            sources=["myext.c"],
            extra_compile_args=["-O2"],
        )
    ]
)
# python setup.py build_ext --inplace
# import myext; myext.add(3, 4)

빌드한 확장 기능 사용

빌드가 완료되면 다른 Python 모듈과 같은 방식으로 확장 기능을 가져옵니다. Python은 myext.so(Windows에서는 .pyd)를 찾아 확장 기능을 로드합니다.

# After: python setup.py build_ext --inplace
import myext
print(myext.add(3, 4))        # 7
print(myext.safe_div(10, 2))  # 5
# myext.safe_div(1, 0)         # ZeroDivisionError

키워드 인수

키워드 목록과 함께 PyArg_ParseTupleAndKeywords를 사용하여 C 함수에서 키워드 인수를 지원합니다.

static char* kwargs[] = {"x", "y", NULL};

static PyObject* hypot_c(PyObject* self,
                          PyObject* args,
                          PyObject* kw) {
    double x, y;
    if (!PyArg_ParseTupleAndKeywords(args, kw, "dd",
                                     kwargs, &x, &y))
        return NULL;
    return PyFloat_FromDouble(sqrt(x*x + y*y));
}

모듈 수준 상수

PyModule_AddIntConstant를 사용하여 PyInit_에서 정수 또는 문자열 상수를 모듈에 추가합니다.

PyMODINIT_FUNC PyInit_myext(void) {
    PyObject* m = PyModule_Create(&module);
    if (!m) return NULL;
    PyModule_AddIntConstant(m, "VERSION", 1);
    PyModule_AddStringConstant(m, "AUTHOR", "Alice");
    return m;
}

GIL 해제

Py_BEGIN_ALLOW_THREADS / Py_END_ALLOW_THREADS로 순수 C 작업을 감싸면 C 코드가 실행되는 동안 다른 Python 스레드가 실행될 수 있습니다.

static PyObject* heavy(PyObject* self, PyObject* args) {
    long n;
    if (!PyArg_ParseTuple(args, "l", &n)) return NULL;
    long result;
    Py_BEGIN_ALLOW_THREADS
        result = slow_c_computation(n);  // GIL released
    Py_END_ALLOW_THREADS
    return PyLong_FromLong(result);
}

확장 기능 테스트

pytest를 사용하여 Python 인터페이스를 통해 C 확장 기능을 테스트합니다. 별도의 C 테스트 도구는 필요하지 않습니다.

# test_myext.py
import pytest
import myext

def test_add(): assert myext.add(3, 4) == 7
def test_zero_div():
    with pytest.raises(ZeroDivisionError):
        myext.safe_div(1, 0)

빠른 확인

Python 예외가 설정되었음을 알리려면 C 확장 기능 함수가 무엇을 반환해야 합니까?

복습

C 확장 기능에는 메서드 함수(인수를 구문 분석하고 PyObject*를 반환), 메서드 표, 모듈 정의 구조체와 PyInit_name()이 필요합니다. PyErr_SetString으로 예외를 설정하고 NULL을 반환하여 예외를 발생시킵니다. 순수 C 작업을 수행할 때는 GIL을 해제하십시오.

자주 묻는 질문

“Python C 확장 모듈 작성” 강의는 무료인가요?

네 — “Python C 확장 모듈 작성” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Python Academy 강의 전체를 잠금 해제할 수 있습니다. Python Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“Python C 확장 모듈 작성”에서 뭘 배우나요?

Python/C API를 사용해 간단한 .so 확장을 만듭니다. 브라우저에서 직접 실행하는 실습 코드로 Python Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Python Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Python Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“Python C 확장 모듈 작성” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Python Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Python Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. C 확장이 필요한 이유: 사용 사례와 절충점
  2. ctypes: Python에서 C 라이브러리 호출하기
  3. cffi: C 외부 함수 인터페이스
  4. Python C 확장 모듈 작성
← Python Academy(으)로 돌아가기