全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-19 10 分钟 ✍️ juanwangdev

Python C API

Python C API允许用C语言扩展Python或嵌入Python解释器,适用于性能关键场景和系统集成。

基础概念

所有Python对象在C层面都是PyObject*指针,包含引用计数和类型指针:

C
// PyObject 结构(简化)
typedef struct _object {
    Py_ssize_t ob_refcnt;       // 引用计数
    PyTypeObject *ob_type;      // 类型对象
} PyObject;

引用计数管理

C
#include <Python.h>

void refcount_demo(PyObject *obj) {
    // 增加引用计数
    Py_INCREF(obj);

    // 减少引用计数
    Py_DECREF(obj);

    // 偷取引用(不增加计数,调用者负责释放)
    Py_DECREF(obj);  // 如果是偷取的引用

    // 借用引用(不拥有,不负责释放)
    // 如 PyList_GetItem 返回借用引用
    PyObject *item = PyList_GetItem(list, 0);  // 借用
    Py_INCREF(item);  // 需要时增加计数
}

注意:引用计数错误是C扩展最常见的问题,务必成对使用INCREF/DECREF。

创建C扩展模块

C
// mymodule.c
#define PY_SSIZE_T_CLEAN
#include <Python.h>

// 示例函数:计算两数之和
static PyObject* my_add(PyObject *self, PyObject *args) {
    double a, b;

    if (!PyArg_ParseTuple(args, "dd", &a, &b)) {
        return NULL;  // 解析失败,返回NULL触发异常
    }

    return PyFloat_FromDouble(a + b);
}

// 方法表
static PyMethodDef MyMethods[] = {
    {"add", my_add, METH_VARARGS, "Add two numbers"},
    {NULL, NULL, 0, NULL}  // 哨兵
};

// 模块定义
static struct PyModuleDef mymodule = {
    PyModuleDef_HEAD_INIT,
    "mymodule",           // 模块名
    "Example module",     // 文档
    -1,                   // 每解释器状态大小,-1表示全局
    MyMethods
};

// 初始化函数
PyMODINIT_FUNC PyInit_mymodule(void) {
    return PyModule_Create(&mymodule);
}

编译安装(setup.py):

Python
from setuptools import Extension, setup

module = Extension(
    'mymodule',
    sources=['mymodule.c']
)

setup(
    name='MyModule',
    version='1.0',
    ext_modules=[module]
)
Bash
python setup.py build_ext --inplace

参数解析

C
// 常用格式字符
// i - int
// l - long
// d - double
// s - char* (UTF-8)
// O - PyObject*
// O! - 特定类型的PyObject*

static PyObject* parse_demo(PyObject *self, PyObject *args) {
    int num;
    const char *str;
    PyObject *list;

    // "isO!" 表示:int, string, 必须是list的对象
    if (!PyArg_ParseTuple(args, "isO!", &num, &str, &PyList_Type, &list)) {
        return NULL;
    }

    // 解析关键字参数
    PyObject *kwlist = PyList_New(0);
    // ...
    return Py_None;
}

// 关键字参数版本
static PyObject* kw_demo(PyObject *self, PyObject *args, PyObject *kwargs) {
    int x = 0, y = 0;
    static char *kwlist[] = {"x", "y", NULL};

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", kwlist, &x, &y)) {
        return NULL;
    }
    return PyLong_FromLong(x + y);
}

嵌入Python解释器

C
#include <Python.h>

int main(int argc, char *argv[]) {
    // 初始化解释器
    Py_Initialize();

    // 执行Python代码
    PyRun_SimpleString("print('Hello from embedded Python!')");

    // 导入模块并调用函数
    PyObject *math = PyImport_ImportModule("math");
    PyObject *sqrt = PyObject_GetAttrString(math, "sqrt");
    PyObject *result = PyObject_CallFunction(sqrt, "d", 2.0);

    printf("sqrt(2) = %f\n", PyFloat_AsDouble(result));

    // 清理
    Py_DECREF(result);
    Py_DECREF(sqrt);
    Py_DECREF(math);

    // 关闭解释器
    Py_Finalize();
    return 0;
}

类型定义

C
// 定义自定义类型
typedef struct {
    PyObject_HEAD
    int value;
} MyObject;

static void MyObject_dealloc(MyObject *self) {
    Py_TYPE(self)->tp_free((PyObject *)self);
}

static PyObject* MyObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
    MyObject *self;
    self = (MyObject *)type->tp_alloc(type, 0);
    if (self != NULL) {
        self->value = 0;
    }
    return (PyObject *)self;
}

static int MyObject_init(MyObject *self, PyObject *args, PyObject *kwds) {
    int value = 0;
    static char *kwlist[] = {"value", NULL};

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &value))
        return -1;

    self->value = value;
    return 0;
}

static PyTypeObject MyObjectType = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymodule.MyObject",
    .tp_doc = "Custom object",
    .tp_basicsize = sizeof(MyObject),
    .tp_itemsize = 0,
    .tp_flags = Py_TPFLAGS_DEFAULT,
    .tp_new = MyObject_new,
    .tp_init = (initproc)MyObject_init,
    .tp_dealloc = (destructor)MyObject_dealloc,
};

要点总结

  1. **PyObject***是所有Python对象的C表示
  2. 引用计数必须严格配对:Py_INCREF/Py_DECREF
  3. **PyArg_ParseTuple**解析位置参数,PyArg_ParseTupleAndKeywords解析关键字参数
  4. 嵌入解释器使用Py_Initialize/Py_Finalize
  5. 类型定义需要实现newinitdealloc等槽位

📝 发现内容有误?点击此处直接编辑

← 上一篇 Python异步同步机制
下一篇 → Python命名空间与作用域实现
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库