在C程序中内嵌Python解释器 用脚本语言实现灵活的Plug

作者:青岛澄润国际贸易有限公司 来源:www.usabcc.com 发布时间:2017-09-02 11:47:25
在C程序中内嵌Python解释器 用脚本语言实现灵活的Plugin机制

在经历过的一些大型项目中,很难独立使用一种开发语言完成任务,由于我这边的业务项目通常以服务器方面居多,从项目周期和运营维护角度考虑,既要考虑到程序的性能,又要考虑到业务功能变更和维护的便利性。
很多时候,我们都会以Python进行框架开发,在一些涉及到性能要求的时候以内嵌C模块的形式进行扩展,以提高整个项目的执行效率。然而我们还有很多以C语言开发的服务器项目,通常使用Prefork、MPM等多进程或多线程的框架,那么怎么才能做到灵活的对这些服务器程序的业务扩展或是Plugin功能呢?
以前在纯C语言时,我们通常采用so lib或是dlopen的方法,这样每次增加或是调整业务模块都需要重新编译业务模块程序,使得联调和Debug相对比较复杂,现在我们可以采用另一种方式,在服务器端程序中嵌入Python解释器,在C程序中需要Kook的地方,以Python程序进行业务处理,灵活的实现Plugin机制,这样对于需要灵活业务调整、联调Debug时,带来了很大的便利性。

现在以一个小的示例程序,介绍在C程序中如何嵌入Python解释器,及如何载入Python脚本程序。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

/**

* @file test.c

*/

#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:

1

2

3

4

5

6

7

8

9

10

11

12

#!/usr/local/bin/python

import sys

def testpy(name):

if not name:

return 'Valid Arguments'

str = "hello, " + name

return str

gcc编译参数:

1

gcc -Wall -O2 -o test test.c -I/usr/local/include/python2.7 -L/usr/local/lib/ -lpython2.7 -Wl,-R/usr/local/lib

程序运行结果:

1

2

[xxx@xxx]$ ./test world

hello, world

当然这种方式处理的很简单,同时也没有考虑更多出错机制的处理,需要后面不断的完善,目前只演示了最基本的使用方法和流程,其实对于Node.js来讲,本质上就是在C/C++中嵌入了V8引擎,增加了很多Hook机制,这样就可以用Javascript快速实现各种业务功能,从性能和开发维护角度,都取得了非常好的成绩,以后也要深入研究研究。

其实可以基于Libevent实现一个MPM的POP3服务器框架,然后对于POP3的业务处理模块,比如认证、获取用户profile、获取邮件索引信息等都可以使用Python脚本来实现,这样就可以方便灵活的定义API的接口形式,进行联调Debug处理,看看接下来的有没有时间开源一个这样的服务器吧。

企业建站2800元起,携手武汉肥猫科技,做一个有见地的颜值派!更多优惠请戳:仙桃SEO http://xiantao.4567w.com

  • 上一篇:20170401
  • 下一篇:最后一页
  •