APP下载

Ubuntu系统中Python无缝调用C程序的实现

2018-12-05韦立梅张淑荣

电脑与电信 2018年9期
关键词:源代码文件夹调用

韦立梅 张淑荣

(广东白云学院,广东 广州 510450)

1 引言

随着人工智能、大数据计算、系统运维、网络爬虫等技术的兴起,Python作为目前最火的脚本语言,以其优雅、简单、功能强大、开发效率高、跨平台等优点,被广泛应用于这些领域。C语言是一种编译型语言,介于高级和低级语言之间,C程序的运行必须要经过编译后,生成机器码,然后再运行,执行速度快,但不能跨平台,目前主要用于操作系统、驱动等底层的开发。在实际开发中,程序员往往会把程序中的性能瓶颈部分的实现,以扩展的方式用C程序来完成,而业务逻辑部分的实现,则用Python这种高度集成、适合开发大型项目的程序设计语言来完成,从而扬长避短,充分发挥出两种语言的各自优势。

2 用C语言扩展Python的流程

(1)创建C源代码(.c);

(2)把C源代码打包成库文件,也就是Python类型适配,创建包裹函数(.c),包装C代码;

(3)编译与测试。

3 具体实现步骤

3.1 创建C程序功能源代码

(1)首先进入Ubuntu系统,这里选择在桌面下,新建一个文件夹pythonexc(以下创建的所有文件/夹都存放在该文件夹中,以方便管理),在该文件夹中创建一个名为MaxRun.c的源文件,实现定义一个求两数最大值的函数maxn,并在主函数main中调用maxn这个函数。具体代码如下:

(2)打开Ubuntu中的终端窗口,使用cd命令进入到桌面的pythonexc文件夹,然后使用gcc命令对C源文件编译链接生成可执行文件后,并运行,看结果是否正确(在这步一定要保证所编写C代码的正确性,以避免在Python中调试C的麻烦),编译及输出结果如下图1所示,若正确,再将main函数重命名为如test(作为扩展模块,不能有main函数,避免同名冲突),才能进行下一步的操作。

图1 gcc编译及运行后的输出结果

(3)编写相应的MaxRun.h头文件,将定义的两个函数maxn和test封装到该头文件里,在包裹模块中需要调用它,代码如下:

3.2 创建包裹模块,包装编写好的C代码

包裹模块是C源代码与Python解释器之间进行交互的桥梁。Python和C就是通过这个模块,完成无缝适配的。在刚建好的pythonexc文件夹中,新建一个名字为MaxRun-Wrapper.c的源文件,作为MaxRun.c的包裹模块。包裹模块的代码从上到下主要分为四部分:

第一部分代码:包含Python.h等的头文件。

Python.h头文件一般存放在/usr/local/include/python2.x中,如果没有可以在终端输入命令:sudo apt-get install python-dev,安装Python。在包裹函数的最上面加入如下四行C代码:

第二部分代码:为被包裹的C功能源代码(MaxRun)中所写的每一个函数(maxn和test)增加一个静态的PyObject*Module_func()的包裹函数。

包裹函数的作用就是在Python和C之间完成数据类型的转换。每个包裹函数的返回类型为PyObject*,包裹函数的名字:模块_函数名,如本例中应为两个函数命名为Max-Run_maxn和MaxRun_test,相应的包裹函数代码及功能说明如图2所示。

图2 包裹函数代码及功能说明

第三部分:为模块增加一个PyMethodDef Module-Methods[]的函数声明数组。

创建完包裹函数后,需要用函数声明数组的方式,把C功能源代码中定义的函数与对应的包裹函数一一列举在数组中,以便Python解释器能够导入并调用这些函数,最后的两个NULL表示函数声明结束。函数声明数组代码及格式说明如图3所示。

图3 函数声明数组的定义及格式说明

第四部分:函数的初始化声明。

初始化声明中的代码,会在包裹模块被python导入时进行调用,完成初始化C模块以及这个模块所包含的函数的作用。初始化声明代码如下:

至此,包裹模块已经全部完成,保存在MaxRunWrapper.c文件中。

3.3 编译安装到Python环境,并测试

为了让Python的扩展能够被创建,需要把C源代码、C源代码头文件、包裹模块文件放在一起编译,放到Python库,以便在其它Python文件中引入这个C扩展。使用Python中的distutils包来编译、安装和分发这些模块、扩展和包。步骤如下:

(1)创建setup.py

在Python中是由setup函数完成编译,应为每一个扩展创建一个Extension实例,我们这里只有一个扩展。setup.py文件中的代码及相关参数说明如图4所示。

图4 setup.py文件代码及相关参数说明

(2)运行setup.py编译和连接C的扩展代码

在Ubuntu终端中执行如下命令:python setup.py build。如果最终能生成一个*.so(这里是MaxRun.so)的动态库文件,表示编译成功。该文件会被存放在pythonexc/bulid/lib.*目录下。

(3)从Python中导入模块和测试

在Ubuntu终端中执行如下命令:sudo python setup.py install。安装我们的setup.py文件,会把生成的动态库文件.so复制到Ubuntu的公共库中,然后就可以用importMaxRun命令导入该扩展模块的动态库文件。可以在ipython中以交互的方式测试,也可以新建一个python文件,用import命令导入该扩展模块,就可以无缝调用C扩展模块中的函数了。

以新建一个pytest.py文件为例,在其中导入C扩展模块,并调用其中的test函数、代码及输出效果如图5所示。

图5 测试文件代码及输出结果

4 结束语

在实际应用开发中,以下两种情况可以考虑用C语言来扩展Python:一是当需要大规模的计算,遇到性能瓶颈的效率提升时;二是需要保持源码的私密性,如加密解密算法时。在用Python开发项目的时候,如果能够有效地借力C程序,可以大大提升程序的效率,是现在很多程序员经常采用的编程方式。

猜你喜欢

源代码文件夹调用
人工智能下复杂软件源代码缺陷精准校正
磁力文件夹
基于TXL的源代码插桩技术研究
核电项目物项调用管理的应用研究
LabWindows/CVI下基于ActiveX技术的Excel调用
软件源代码非公知性司法鉴定方法探析
调动右键 解决文件夹管理三大难题
基于系统调用的恶意软件检测技术研究
揭秘龙湖产品“源代码”
TC一键直达常用文件夹