You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Python字典作为参数传递给C语言函数

问题原因

你遇到的报错有两个核心原因:

  1. ctypes默认不会自动将Python字典转换为C层需要的PyObject*类型,你没有显式声明参数类型,所以ctypes不知道如何转换入参
  2. 如果要写标准Python C扩展,你的C函数签名不符合Python C API的要求,缺少参数解析逻辑

可以直接将Python字典传递给C函数,下面给出两种可行的解决方案:


方案1:适配现有ctypes调用逻辑

不需要修改太多原有代码,只补充类型声明即可:

修正C代码

#include <Python.h>
#include <stdio.h>
#include <stdlib.h>

PyObject* changeDict(PyObject* dict) {
    if(PyDict_Check(dict)) {
        system("echo '==== is a dict ====' | systemd-cat -t 'little.c'");
        // 示例:修改字典内的status值为1
        PyDict_SetItemString(dict, "status", PyInt_FromLong(1));
    }
    // 手动增加引用计数,避免Python GC提前回收对象导致内存错误
    Py_INCREF(dict);
    return dict;
}

修正Python代码

显式声明参数和返回值的类型为py_object:

from ctypes import *

mydll = PyDLL("little.so")
# 新增类型声明
mydll.changeDict.argtypes = [py_object]
mydll.changeDict.restype = py_object

dic = {"status": 0}
dic = mydll.changeDict(dic)
print(dic)

编译和部署so文件的逻辑不需要修改,运行后输出为{'status': 1}即为正常。


方案2:编写标准Python C扩展(更稳定,推荐)

完全遵循Python C扩展规范,不需要依赖ctypes调用,兼容性更好:

重写C代码

#include <Python.h>
#include <stdio.h>
#include <stdlib.h>

// 符合规范的C扩展函数签名,固定为self + args两个入参
static PyObject* little_changeDict(PyObject* self, PyObject* args) {
    PyObject* dict;
    // 解析传入的参数,"O"表示接收一个Python对象
    if (!PyArg_ParseTuple(args, "O", &dict)) {
        return NULL;
    }
    if(PyDict_Check(dict)) {
        system("echo '==== is a dict ====' | systemd-cat -t 'little.c'");
        PyDict_SetItemString(dict, "status", PyInt_FromLong(1));
    }
    Py_INCREF(dict);
    return dict;
}

// 扩展方法表
static PyMethodDef LittleMethods[] = {
    {"changeDict", little_changeDict, METH_VARARGS, "修改传入的Python字典"},
    {NULL, NULL, 0, NULL}
};

// 模块初始化函数(Python2版本,Python3需改名为PyInit_little)
PyMODINIT_FUNC initlittle(void) {
    (void) Py_InitModule("little", LittleMethods);
}

编译命令

gcc -g -fPIC -shared little.c -I/usr/include/python2.7 -lpython2.7 -o little.so

测试Python代码

不需要引入ctypes,直接导入扩展模块即可:

import little

dic = {"status": 0}
dic = little.changeDict(dic)
print(dic)

注意事项

  • 操作Python对象时要注意引用计数管理,避免出现内存泄漏或者野指针问题
  • 如果升级到Python3,代码中的PyInt_FromLong需要改成PyLong_FromLong,模块初始化函数名同步修改为PyInit_little
  • 字典增删改查可以直接使用Python C API提供的PyDict_GetItemString、PyDict_DelItemString等方法实现

内容的提问来源于stack exchange,提问作者Jack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 03:36:04