30. Python脚本学习笔记三十 更多关于SWIG
本篇名言:“高雅的人,看背影就知道;奋进的人,听脚步声就知道;和善的人,看笑容就知道;优秀的人,看你就知道!”
在https://python.org/doc/ 链接上可以找到更多PythonC API的知识。
本篇题目虽然是更多关于SWIG,其实和SWIG并无关系,只是SWIG相关的那些扩展。
1. 引用计数
在Python中和JAVA中类似,内存管理是自动的,只要创建对象,如果不再使用就会消失。但是C语言不是这种情况的。
所以当编写Python扩展时,需要访问Python管理内存的工具。其中之一就是引用计数。一个对象只要被代码中的某部分所引用,那个对象就不应该被释放掉。当一个对象的引用数目变成0后,数目就不会再增加了。
Python中共有两个宏Py_INCREF和Py_DECREF分别来增加和减少一个对象的引用计数。
具体使用可以查看https://python.org/doc/ 中相关文档,大体如下图片汇总。
引用计数是垃圾收集的一种,其中垃圾指的是程序不再使用的对象。
通过GC模块可以再程序中访问Python的垃圾收集器。
2. 扩展用的框架
在编写Python的时候需要很多重复代码。使用工具SWIG,Pyrex和modulator比较好的原因是它们会自动复制代码。
我们要记住的是Python.h头文件必须首先被包含,要在其他标准头文件之前。
由于函数能被任何东西调用,所以应该是静态的,返回一个指向PyObject类型的对象。的指针,有两个参数,两个参数都是指向PyObject的指针。
3. 一个样板
函数文件palindrome2.c
内容如下:
#include <Python.h>
static PyObject *is_palindrome(PyObject *self, PyObject *args) {
int i, n;
const char *text;
int result;
/* "s" means asingle string: */
if (!PyArg_ParseTuple(args,"s", &text)) {
return NULL;
}
/* The old code, more orless: */
n=strlen(text);
result = 1;
for (i=0; i<=n/2; ++i) {
if (text[i] !=text[n-i-1]) {
result = 0;
break;
}
}
/* "i" means asingle integer: */
returnPy_BuildValue("i", result);
}
/* A listing of our methods/functions: */
static PyMethodDef PalindromeMethods[] = {
/* name, function, argumenttype, docstring */
{"is_palindrome",is_palindrome, METH_VARARGS, "Detect palindromes"},
/* An end-of-listingsentinel: */
{NULL, NULL, 0, NULL}
};
/* An initialization function for the module (the name is
significant): */
PyMODINIT_FUNC initpalindrome() {
Py_InitModule("palindrome", PalindromeMethods);
}
需要注意初始化函数的名字必须是initmodule,module是具体模块的名字。
编译如下:
#gcc -fPIC -I/usr/include/python2.6 -shared palindrome2.c -o palindrome.so
然后在Python中运行如下:
>>> from palindrome importis_palindrome
>>> is_palindrome('foobar')
0
>>> is_palindrome('deified')
1