http://www.cnblogs.com/haippy/archive/2011/09/17/2179902.htmlhtml
python是一門藝術語言,除了開發桌面程序,還可以開發網絡應用,數據庫應用,還能夠代替shell編寫一些的實用腳本,本文主要講述瞭如何利用 python 程序控制你的 C 程序的行爲。python
做爲例子,本文將用 python 和 C 語言來編寫示例代碼,同時也會順便介紹一下 利用 C 語言擴展 python的方法,最後會給出完整的 C 編寫 python 模塊的源碼。linux
首先考慮如下應用:假設你須要在項目中實現字符串排序比較的功能,可是事先並不肯定應該如何排序(再次假設一下,若是某字符串中若是出現了 「aaa」, "bbb" 這樣的子串,就將該字符串排在靠後的位置),此時若是用 C 語言實現了預約義的排序功能,那麼萬一某天須要改變字符串排序行爲,就必須從新編寫 C 程序的實現,而且再次編譯項目,這樣會浪費大量的精力,相反,若是將字符串排序的功能用 python 代碼控制,即如何排序由python程序定義,這樣將大大提升程序的靈活性。shell
如下就是示例程序,程序由 python 腳本和 C 編譯的 python 模塊組成,python 實現字符串比較功能,爲了簡化期間,本文只是先兩個字符串大小的比較(用於說明 python控制程序行爲已經足夠),程序採用回調函數實現,完整代碼以下:數據庫
python模塊:網絡
/* * ===================================================================================== * * Filename: ext.c * * Description: * * Version: 0.1.0 * Created: 09/16/2011 05:44:40 PM * Revision: r1 * Compiler: gcc * * Author: Fu Haiping <haipingf@gmail.com> * Company: ICT * * ===================================================================================== */ #include <Python.h> static PyObject *my_callback = NULL; static PyObject * _set_callback(PyObject *self, PyObject *args) { PyObject *result = NULL; PyObject *temp; if (PyArg_ParseTuple(args, "O", &temp)) { if (!PyCallable_Check(temp)) { PyErr_SetString(PyExc_TypeError, "parameter must be callable"); return NULL; } Py_XINCREF(temp); /* Add a reference to new callback */ Py_XDECREF(my_callback); /* Dispose of previous callback */ my_callback = temp; /* Remember new callback */ /* Boilerplate to return "None" */ Py_INCREF(Py_None); result = Py_None; } return result; } static int _compare(const char *a, const char *b) { long ret; PyObject *arglist; PyObject * result = NULL; arglist = Py_BuildValue("(ss)", a, b); result = PyEval_CallObject(my_callback, arglist); ret = PyInt_AsLong(result); if (result == NULL) return -1; Py_DECREF(result); return ret; } void compare(const char *a, const char *b) { if (_compare(a, b) > 0) { printf("arg1 is greater than arg2\n"); } else if (_compare(a, b) < 0) { printf("arg1 is NOT greater than arg2\n"); } else { printf("arg1 is equal to arg2\n"); } } static PyObject* _compare_callback(PyObject *self, PyObject *args) { const char *a = NULL, *b = NULL; if (!PyArg_ParseTuple(args, "ss", &a, &b)) { return NULL; } compare(a, b); Py_INCREF(Py_None); return Py_None; } static PyMethodDef extMethods[] = { {"setcmp", _set_callback, METH_VARARGS}, {"compare", _compare_callback, METH_VARARGS}, {NULL, NULL} }; void initext() { Py_InitModule("ext", extMethods); }
setup.py 文件:函數
from distutils.core import setup, Extension module1 = Extension('ext', sources = ['ext.c']) setup (name = 'ext', version = '1.0', description = 'This is a demo package', ext_modules = [module1])
執行過程:ui
$ python Python 2.6.6 (r266:84292, Sep 15 2010, 15:52:39) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import ext >>> def compare(a, b): ... if (a > b): ... return -1 ... if (a < b): ... return 1 ... if (a ==b): ... return 0 ... >>> setcmp(compare) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'setcmp' is not defined >>> ext.setcmp(compare) >>> ext.compare("aaa", "bbb") arg1 is greater than arg2 >>>
上述執行過程當中,咱們利用了 pythoon 的 compare函數,該函數實現字符串的比較,若是 a > b, 返回 -1,a < b, 返回1, a == b, 返回0, 這和咱們日常的比較方式相反,因此最後的結果中咱們能夠看到比較 "aaa", "bbb" 時,"aaa" 會比 「bbb」 大。spa
若是使用 python 定義咱們常規的字母排序的比較函數,會看到以下執行結果:3d
>>> def compare_ex(a, b): ... if (a > b): ... return 1 ... if (a < b): ... return -1 ... if (a == b): ... return 0 ... >>> ext.setcmp(compare_ex) >>> ext.compare("aaa", "bbb") arg1 is NOT greater than arg2
此時,"aaa" 就比 "bbb" 小。
結論,以上只是一個小小的嘗試,python的靈活性遠遠不止如此,Haippy會繼續探索 python的一些有趣的特性和使用方法,請關注本博客後續文章。:-)