2010年(5)
分类: Python/Ruby
2010-01-14 12:55:36
python的强大不仅表现在其功能上,而且还表现在其扩展能力上。
使用C/C++很容易编写python的模块,扩展python的功能。
同时将性能要求比较高的代码使用C/C++编写,能更好的弥补
脚本语言执行速度慢的缺陷。
1. python的C语言扩展
1.1 TestCLib.c: 提供python的模块接口
#include "Python.h"
#include
#include
long fac(long);
// ------------------------------------------------------
// Make C code
usable in Python
//
------------------------------------------------------
PyObject*
TestCLib_fac(PyObject * self, PyObject *args)
{
long num;
if ( ! PyArg_ParseTuple(args,"l",&num)){
return
NULL;
}
return
(PyObject*)Py_BuildValue("l",fac(num));
}
static PyMethodDef
TestCLibMethods[] = {
{"fac",TestCLib_fac,METH_VARARGS},
{NULL,NULL}
};
void initTestCLib()
{
Py_InitModule("TestCLib",TestCLibMethods);
}
1.2 test.c: 具体的C语言实现
#include
#include
// ------------------------------------------------------
// Pure C
code
// ------------------------------------------------------
long fac(long n)
{
if ( n < 0){
return
fac(-n);
} else if ( n < 2 ){
return 1;
} else
{
return n * fac(n-1);
}
}
1.3 test.py: 测试脚本
#!/usr/bin/env python
import TestCLib as TestLib
for i in range(10,20) :
f1 = TestLib.fac(i)
print "%d! =
%d"%(i,f1)
1.4 编译与运行
编译命令:
gcc -fPIC -shared -o TestCLib.so TestCLib.c test.c -I
/usr/local/python/include/python2.6/
将生成的动态链接库 TestCLib.so 和 test.py
放在同一个目录下
运行命令:
python test.py
2. python 的C++扩展
2.1 test.h 类的定义
#ifndef _TEST_H_
#define
_TEST_H_
namespace Test{
class CTest{
public:
long
fac(long);
};
}
#endi
2.2 test.cpp 类的实现
#include
#include
#include "test.h"
// ------------------------------------------------------
// Pure CPP
code
// ------------------------------------------------------
namespace Test{
long CTest::fac(long n)
{
if ( n
< 0){
return fac(-n);
} else if ( n < 2
){
return 1;
} else {
return n *
fac(n-1);
}
}
}
2.3 TestCPPLib.cpp: python的模块接口
#include "Python.h"
#include
"test.h"
// ------------------------------------------------------
// Make CPP code
usable in Python
//
------------------------------------------------------
PyObject*
TestCPPLib_fac(PyObject * self, PyObject *args)
{
Test::CTest
test;
long num;
if ( ! PyArg_ParseTuple(args,"l",&num)){
return
NULL;
}
return
(PyObject*)Py_BuildValue("l",test.fac(num));
}
static PyMethodDef
TestCPPLibMethods[] = {
{"fac",TestCPPLib_fac,METH_VARARGS},
{NULL,NULL}
};
extern "C" void
initTestCPPLib()
{
Py_InitModule("TestCPPLib",TestCPPLibMethods);
}
2.4 test.py: 测试脚本
#!/usr/bin/env python
import TestCPPLib as TestLib
for i in range(10,20) :
f1 = TestLib.fac(i)
print "%d! =
%d"%(i,f1)
2.5 编译运行
编译命令:
g++ -fPIC -shared -o TestCPPLib.so TestCPPLib.cpp
test.cpp -I /usr/local/python/include/python2.6/
将TestCPPLib.so 和 test.py
放在同一个目录下
运行命令:
python test.py
2.6 注意:
在c++的python模块接口中:初始化函数init需要使用extern "C"声明。
如果上述
initTestCPPLib() 直接定义为:
void initTestCPPLib()
{
Py_InitModule("TestCPPLib",TestCPPLibMethods);
}
则在运行test.py时,会提示错误:
dynamic
module does not define init function
原因是由于g++在编译时改变了函数名,
而python按照名字查找模块初始化函数,自然会找不到了。
3. 总结
python的导出函数的原型是:
PyObject* fun(PyObject * self, PyObject*
args);
同时对于模块mo,需要编写初始化函数initmo.