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解释器注册改模块中所有可能用到的方法。

 

posted @ 2022-05-12 16:04  Aemnprsu_wx  阅读(200)  评论(0编辑  收藏  举报