PyObject C语言扩展
python的C语言接口
PyObject
所有对象在python解释器中都被表示成PyObject
PyObject包含Python对象所有成员的指针,并且对对象的类型信息和引用计数进行维护。
在Python扩展编程中,一旦要在C/C++中对Python对象进行处理,就要维护一个PyObject结构
内存管理:
Python通过引用计数机制实现垃圾自动回收,简化内存管理。
每个对象都有一个引用计数,引用+1 销毁-1,计数为零从内存中清空
Python的C语言接口提供宏对引用计数进行维护:
Py_INCREF() +1
Py_DECREF() -1
C中使用Python数据类型
// build an integer PyObject* pInt = Py_BuildValue("i", 2003); assert(PyInt_Check(pInt)); int i = PyInt_AsLong(pInt); Py_DECREF(pInt); // build a float PyObject* pFloat = Py_BuildValue("f", 3.14f); assert(PyFloat_Check(pFloat)); float f = PyFloat_AsDouble(pFloat); Py_DECREF(pFloat); // build a string PyObject* pString = Py_BuildValue("s", "Python"); assert(PyString_Check(pString); int nLen = PyString_Size(pString); char* s = PyString_AsString(pString); Py_DECREF(pString);
列表
// create the list PyObject* pList = PyList_New(3); // new reference assert(PyList_Check(pList));
// set some initial values for(int i = 0; i < 3; ++i) PyList_SetItem(pList, i, Py_BuildValue("i", i));
// insert an item PyList_Insert(pList, 2, Py_BuildValue("s", "inserted"));
// append an item PyList_Append(pList, Py_BuildValue("s", "appended"));
// sort the list PyList_Sort(pList);
// reverse the list PyList_Reverse(pList);
// fetch and manipulate a list slice PyObject* pSlice = PyList_GetSlice(pList, 2, 4); // new reference for(int j = 0; j < PyList_Size(pSlice); ++j) { PyObject *pValue = PyList_GetItem(pList, j); assert(pValue); } Py_DECREF(pSlice);
// cleanup Py_DECREF(pList);
字典
// create the dictionary PyObject* pDict = PyDict_New(); // new reference assert(PyDict_Check(pDict));
// add a few named values PyDict_SetItemString(pDict, "first", Py_BuildValue("i", 2003)); PyDict_SetItemString(pDict, "second", Py_BuildValue("f", 3.14f));
// enumerate all named values PyObject* pKeys = PyDict_Keys(); // new reference for(int i = 0; i < PyList_Size(pKeys); ++i) { PyObject *pKey = PyList_GetItem(pKeys, i); PyObject *pValue = PyDict_GetItem(pDict, pKey); assert(pValue); } Py_DECREF(pKeys); // remove a named value
PyDict_DelItemString(pDict, "second"); // cleanup Py_DECREF(pDict);
封装Python可调用的C模块
PyObject* wrap_fact(PyObject* self, PyObject* args) { int n, result; if (! PyArg_ParseTuple(args, "i:fact", &n)) //i:单个Int ii:多个int 后面相应增加对应的参数 return NULL; result = fact(n); return Py_BuildValue("i", result);//i对应result单个返回值 }
调用函数
int fact(int n) { //if (n <= 1) //return 1; // else return n * (n + 1); }
包含三部分:导出函数,方法列表,初始化函数
1)导出函数:
PyObject* method(PyObject* self, PyObject* args);
该函数是Python解释器和C函数进行交互的接口
参数解释
self:只在C函数被实现为内联方法(built-in method)时才使用,通常为空(NULL)
args:包含Python解释器要传递给C的所有参数,通常使用PyArg_ParseTuple()来获得参数值。
所有导出函数都返回一个PyObject指针,如果对应C函数没有返回值(void),则应返回一个全局的
None对象(Py_None),引用计数+1
2)方法列表
static PyMethodDef exampleMethods[] = { {"fact", wrap_fact, METH_VARARGS, "Caculate N!"}, {NULL, NULL} };
由四部分组成:方法名、导出函数、参数传递方式、方法描述
参数传递方式:METH_VARARGS 参数传递的标准形式,通过Python的元组在Python解释器和C函数之间传递参数
METH_KEYWORD Python解释器和C函数之间将通过Python的字典类型在两者之间进行参数传递。
3)初始化函数:
void initexample() { PyObject* m; m = Py_InitModule("example", exampleMethods); }
解释器规定所有初始化函数的函数名必须都init开头,加上模块的名字
导入模块将根据模块名称查找相应初始化函数,初始化函数通过调用Python的C语言扩展接口提供的
Py_InitModule()函数,向Python解释器注册改模块中所有可能用到的方法。