在經歷過的一些大型項目中,很難獨立使用一種開發語言完成任務,因爲我這邊的業務項目一般以服務器方面居多,從項目週期和運營維護角度考慮,既要考慮到程序的性能,又要考慮到業務功能變動和維護的便利性。
不少時候,咱們都會以Python進行框架開發,在一些涉及到性能要求的時候之內嵌C模塊的形式進行擴展,以提升整個項目的執行效率。然而咱們還有不少以C語言開發的服務器項目,一般使用Prefork、MPM等多進程或多線程的框架,那麼怎麼才能作到靈活的對這些服務器程序的業務擴展或是Plugin功能呢?
之前在純C語言時,咱們一般採用so lib或是dlopen的方法,這樣每次增長或是調整業務模塊都須要從新編譯業務模塊程序,使得聯調和Debug相對比較複雜,如今咱們能夠採用另外一種方式,在服務器端程序中嵌入Python解釋器,在C程序中須要Kook的地方,以Python程序進行業務處理,靈活的實現Plugin機制,這樣對於須要靈活業務調整、聯調Debug時,帶來了很大的便利性。python
如今以一個小的示例程序,介紹在C程序中如何嵌入Python解釋器,及如何載入Python腳本程序。服務器
/** * @file test.c * gcc -Wall -O2 -o test test.c -I/usr/include/python2.7 -L/usr/lib -lpython2.7 -Wl,-R/usr/local/lib */ #include <stdio.h> #include <string.h> #include <Python.h> int main(int argc, char *argv[]) { PyObject *pmod = NULL; PyObject *pstr = NULL; PyObject *pfunc = NULL; PyObject *pargs = NULL; char *cstr = NULL; /* 初始化解釋器 */ Py_Initialize(); /* 構建一個元組保存參數, PyEval_CallObject的第二參數是一個元組 */ pargs = Py_BuildValue("(s)", argv[1]); /* 添加Python路徑, 包括當前路徑, 不然不能導入當前路徑下的模塊 */ PyRun_SimpleString("import sys;sys.path.append('.')"); /* 導入模塊名稱, 一般爲調用的Python腳本程序名 */ pmod = PyImport_ImportModule("testpy"); if (pmod == NULL) { printf("import module failed!\n"); return -1; } /* 得到導入模塊的函數屬性 */ pfunc = PyObject_GetAttrString(pmod, "testpy"); if (pfunc == NULL) { printf("No such attribute!\n"); return -1; } /* 調用導入模塊的入口函數, 獲取返回結果 */ pstr = PyEval_CallObject(pfunc, pargs); if (pstr == NULL) { printf("callobject failed!\n"); return -1; } /* 分析返回的結果 */ PyArg_Parse(pstr, "s", &cstr); printf("%s\n", cstr); /* 關閉解釋器 */ Py_Finalize(); return 0; }
在C程序中嵌入的Python腳本程序示例,testpy.py:多線程
#!/usr/bin/env python import sys def testpy(name): if not name: return 'Valid Arguments' str = "hello, " + name return str
程序運行結果:app
~/prg/mypython$ ./test world!框架
hello, world!python2.7
一個更簡單的例子:函數
/* * gcc -Wall -O2 -o test_python test_python.c -I/usr/include/python2.7 -L/usr/lib -lpython2.7 */ #include <Python.h> int main(int argc, char *argv[]) { Py_Initialize(); PyRun_SimpleString("from time import time,ctime"); PyRun_SimpleString("print 'Today is',ctime(time()) "); PyRun_SimpleString("print '^oo^'"); Py_Finalize(); return 0; }
$ ./test_python 性能
Today is Mon Mar 14 00:08:41 2016ui
^oo^spa