Python的C语言扩展

Python016

Python的C语言扩展,第1张

C-Python,或者CPython,指C实现的Python虚拟机的基础API。最通用的Python就是是基于C实现的,它的底层API称为C-Python

API,所有Python代码的最终变成这些API以及数据结构的调用,才有了Python世界的精彩。

Cython,准确说Cython是单独的一门语言,专门用来写在Python里面import用的扩展库。实际上Cython的语法基本上跟Python一致,而Cython有专门的“编译器”先将

Cython代码转变成C(自动加入了一大堆的C-Python

API),然后使用C编译器编译出最终的Python可调用的模块

GIL:Global

Interpreter

Lock,是Python虚拟机的多线程机制的核心机制,翻译为:全局解释器锁。其实Python线程是操作系统级别的线程,在不同平台有不同的底层实现(如win下就用win32_thread,

posix下就用pthread等),Python解释器为了使所有对象的操作是线程安全的,使用了一个全局锁(GIL)来同步所有的线程,所以造成“一个时刻只有一个Python线程运行”的伪线程假象。GIL是个颗粒度很大的锁,它的实现跟性能问题多年来也引起过争议,但到今天它还是经受起了考验,即使它让Python在多核平台下CPU得不到最大发挥。

就算你的项目中有大量的Python代码,你也依旧可以有条不紊地通过将其分离为多个文件或模块加以组织管理。而且你可以从一个模块中选取代码,而从另一个模块中读取属性。更棒的是,对于所有模块,Python的访问语法都是相同的。不管这个模块是Python标准库中的还是你一分钟之前创造的,哪怕是你用其他语言写的扩展都没问题!借助这些特点,你会感觉自己根据需要“扩展”了这门语言,而且你已经这么做了。

代码中的瓶颈,可能是在性能分析中总排在前面的那些热门或者一些特别强调性能的地方,可以作为Python扩展用C重写。需要重申的是,这些接口和纯Python模块的接口是一模一样的,乃至代码和对象的访问方法也是如出一辙的。唯一不同的是,这些代码为性能带来了显著的提升。自然,这全部取决你的应用程序以及它对资源的需求情况。很多时候,使用编译型代码重写程序的瓶颈部分绝对是益处多多的,因为它能明显提升整体性能。

程序设计语言中的这种可扩展性使得工程师能够灵活附加或定制工具,缩短开发周期。虽然像C、C++乃至Java等主流第三代语言(3GL)都拥有该特性,但是这么容易地使用C编写扩展确实是Python的优势。此外,还有像PyRex这样的工具,允许C和Python混合编程,使编写扩展更加轻而易举,因为它会把所有的代码都转换成C语言代码。

因为Python的标准实现是使用C语言完成的(也就是CPython),所以要使用C和C++编写Python扩展。Python 的Java实现被称作Jython,要使用Java编写其扩展。最后,还有IronPython,这是针对.NET或Mono平台的C#实现。你可以使用C#或者VB.Net扩展IronPython.

大概有三种常用方法:

1>使用ctypes模块来调用C写的共享库,比如:

[python] view plain copy print?

#测试ctypes调用linux动态库的能力

from ctypes import *

lib = CDLL("libc.so.6")

printf = lib.printf

printf("Hello World\n")

#查找动态库

from ctypes.util import find_library

print find_library('c')

output = CDLL(find_library("c")).printf

output("测试成功!\n")

但是用它来调用C++写的so就不太合适,因为编译时c++函数名修饰会给你的函数取一个特殊的字符串,你不能在你的python代码里直接使用此函数名,除非你使用的是修饰后的函数名。(在linux下你可以用nm来查看so中的函数名)

2>用C来写python的扩展模块,这个没怎么用过,以后使用时再记录在此。

3>用C++来写python扩展模块:

我是使用Boost.Python来写扩展的,先上工作中的代码片段:

[python] view plain copy print?

#include <boost/python.hpp>//包含boost.python头文件

#include <cstdio>

#include <string>

using namespace boost::python//引入命令空间

class lshw //定义一个类

{

public:

lshw()

virtual ~lshw()

void scan_device()

string get_xml()

private:

hwNode *computer

}

lshw::lshw()

{

computer = new hwNode("computer", hw::system)

}

lshw::~lshw()

{

if (computer)

delete computer

}

void lshw::scan_device()

{

enable("output:numeric")

disable("output:sanitize")

scan_system(*computer)

}

string lshw::get_xml()

{

return computer->asXML()

}

void hello()

{

std::cout <<"Hello World!" <<std::endl

}

BOOST_PYTHON_MODULE(lshw)

{

class_<lshw, boost::noncopyable >("lshw", "This is a lshw project python extend", init<>())//导出类中的方法

.def("scan_device", &lshw::scan_device)

.def("get_xml", &lshw::get_xml)

def("hello",&hello)//导出方法

}

使用boost.python其实结构很简单,你只要写很少的boost.python的代码,你可以把大部分的精力放在C++功能代码上,花很少的精力就可以把它扩展成python的模块。下面是我在Ubuntu11.10上的编译过程:

首先安装boost.python:

sudo apt-get install libboost-python1.46.1

再来编译生成so共享库文件:

g++ -shared -fPIC lshw.cc -o lshw.so -lboost_python

使用:

[python] view plain copy print?

import lshw

hw = lshw.lshw()

lshw.hello()

hw.scan_device()

xml = self.hw.get_xml()