pythonc扩展模块
1. python 可扩展主要体现
就算你的项目中有大量的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.
2. 如何用wintc编译Python的c扩展
python
setup.py
build
--compiler=mingw32
执行后会在当前目录生成一个build目录及文件:
build\lib.win32-2.6\add.pyd
将add.pyd拷贝到当前目录,并写一个测试文件test.py,代码如下:
import
add
print
add.add(3,4)
执行一下,输出为7
OK,基本上就是如此了。
3. 如何建立我的C扩展使用MinGW-W64在Python
安装Python的 windows扩展模块时发生Unable to find vcvarsall.bat的错误,解决方法如下: 首先安装MinGW,在MinGW的安装目录下找到bin的文件夹,找到mingw32-make.exe,复制一份更名为make.exe; 把MinGW的路径添加到环境变量path中,
4. Python的C语言扩展
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得不到最大发挥。
5. 如何编译C++文件为Python扩展模块
大概有三种常用方法:
1>使用ctypes模块来调用C写的共享库,比如:
[python] view plain 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 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::nonable > ("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 print?
import lshw
hw = lshw.lshw()
lshw.hello()
hw.scan_device()
xml = self.hw.get_xml()
6. python怎么作为c语言的扩展
1.环境配置,python3.2装好,编译器我直接用的devcpp的编译器(原因是直接安装就可以,其它的编译器我还不会用),将devcpp的bin目录添加到环境变量path中。
2.准备好your_mole.c文件,这是你自己的C语言写的扩展程序,确保你的your_mole.c符合python和C的接口要求。
3.python提供了distutils模块用来方便地将c文件转变成pyd文件,也是笔者比较推荐的方法。准备好your_mole.c文件后,在同一目录下创建steup.py文件,文件内容如下:
from distutils.core import setup, Extension
mole1 = Extension('your_mole_name',
sources = ['demo.c'])
setup (name = 'PackageName',
version = '1.0',
description = 'This is a demo package',
ext_moles = [mole1])
注意'your_mole_name'要跟C文件中PyInit_mole函数的'mole'一样,否则在后续的步骤中会出错。
4.建立steup.bat文件,内容只有两行:
python.exe setup.py build -c mingw32
pause
5.运行steup.bat文件。
6.如果没有错误,在build\lib.win32-3.2下找到生成的pyd文件,放置到PYTHONPATH的目录中即可被import调用,到此大功告成。注意,python寻找pyd文件不是在sys.path中找,而是在PYTHONPATH指定的目录中找。