Pyrex 一个简单但完整的例子来测试pyrex调用已有lib库法。 ::-- ZoomQuiet [2006-12-06 05:01:07]

CPUG联盟::

CPUG::门户plone

BPUG

SPUG

ZPUG

SpreadPython Python宣传

1. 坐以论道,起而行之

1.1. 尝试 Pyrex

1.1.1. 生成简单的lib

1,先生成简单的lib:

=>vi test.h
int tadd(int a, int b);

=>vi test.c
#include "test.h"
int tadd(int a, int b)
{
       return a+b;
};

=>gcc -c test.c
 生成test.o
=>ar -rsv libtest.a test.o
 生成了 libtest.a 静态库

1.1.2. lib可用?

2,我们测试一下这个lib可以用吗?

=>vi ttest.c
#include <stdio.h>
#include "test.h"
void main(int argc, void * argv[])
{
       int c=1;
       c = tadd(1, 4);
       printf("c = %d \r\n", c);
}

=>gcc ttest.c -ltest -L.
 生成了a.out
 ./a.out 结果是:
 c = 5

证明我们的lib库是可以正常工作的

1.1.3. python的测试模块

3,写一个python的模块td,调用它libtest里的tadd()函数

写一个pyx,

=>vi td.pyx
cdef extern from "test.h":
       int tadd(int i, int j)

def tdadd(int i, int j):
       cdef int c
       c=tadd(i, j)
       return c

就在这行调用的:c=tadd(i, j)了。

编译:

=>pyrexc td.pyx
 生成 td.c
=>gcc -c -fPIC -I/usr/include/python2.4/ td.c
 生成td.c
=>gcc -shared td.o -ltest -L. -o td.so
 生成了td.so。这个就是python可以用的模块so了

1.1.4. 安装

=>vi setup.py
from distutils.core import setup
from distutils.extension import Extension
from Pyrex.Distutils import build_ext
setup(
 name = "PyrexGuide",
 ext_modules=[
   Extension("td", ["td.pyx"], libraries = ["test"])
   ],
 cmdclass = {'build_ext': build_ext}
)
=>python setup.py build_ext --inplace

1.1.5. 测试

>>> import td
>>> dir(td)
['__builtins__', '__doc__', '__file__', '__name__', 'tdadd']
>>> td.tdadd(1,2)
3

呵呵,OK了。

等会再试一试ctypes

1.2. 对比ctypes

继续测试ctypes的用法: 下载ctypes,安装好。

先把刚才的静态test.o编译成动态链接库:

=>gcc -shared test.o -o test.so

然后=>python
>>> from ctypes import *
>>> libt = CDLL("test.so")
>>> libt
<CDLL 'test.so', handle 81ae8b0 at b7de004c>
>>> a= libt.tadd(1, 3)
>>> print a
4

哇哇,好像更加方便了。

1.3. 总结

两者都是扩展了python调用外部lib途径。好像pyrex更强调调用静态的lib,而且是把lib编译成python自己原生的module。 为了做到这个,除了有lib的.a文件外,必须要有lib的.h文件。 ctypes则是显示的调用动态的lib,只要有lib的.so,.dll就可以,目前ctypes已经成为2.5的内部module。 而pyrex还有一个比较重要特点就是可以用类c的语法写python的moduele。

比较同意这个观点: > 我觉得 Pyrex 主要是用来为 c 库 提供一个 pythinic 的接口,而非优化python程序。

目前的例子非常简单,复杂情况下的调用有可能出现的问题都还没有碰到。Zoom给的文章里说到的复杂的结构,联合的情况 也还没有尝试。

想到要调用的lib的线程,指针,内存块操作,就有点头痛。 初步还是决定采用ctypes的方式,工作量上要少写一点东西,至少调试的时候也更直接一点。

一切都根据实际情况来做吧,要试错。

2. 反馈