Chinaunix首页 | 论坛 | 博客
  • 博客访问: 59130
  • 博文数量: 5
  • 博客积分: 1410
  • 博客等级: 上尉
  • 技术积分: 55
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-13 13:01
文章分类
文章存档

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.

阅读(8347) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~