在C程序中內嵌Python解釋器 用腳本語言實現靈活的Plugin機制

在經歷過的一些大型項目中,很難獨立使用一種開發語言完成任務,因爲我這邊的業務項目一般以服務器方面居多,從項目週期和運營維護角度考慮,既要考慮到程序的性能,又要考慮到業務功能變動和維護的便利性。
不少時候,咱們都會以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

相關文章
相關標籤/搜索