如何将Python字典作为参数传递给C语言函数
问题原因
你遇到的报错有两个核心原因:
- ctypes默认不会自动将Python字典转换为C层需要的
PyObject*类型,你没有显式声明参数类型,所以ctypes不知道如何转换入参 - 如果要写标准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
相关产品推荐
相关产品推荐

