Size: 3787
Comment:
|
Size: 2350
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 12: | Line 12: |
附件:教程所用代码下载 attachment:pyxx.rar | === ybeetle === '''060817分享 ''' * 附件:教程所用代码下载 attachment:pyxx.rar * [:YbeetLeTryPyrex:快速尝试Pyrex和C++] === feihu === '''061206 列表分享''' |
Line 14: | Line 19: |
=== 准备的条件: === {{{ 1. Python2.4安装 2. Pyrex安装必须是版本 Pyrex-0.9.4.1 才可以与C++编译 3. Dev-C++ 编译器 (版本最好是 4.9.9.2或以上) Linux 下用 g++ 就行 4. 如果windows下必须要先修正 Python24.lib (在我的例程附件中带有修正后的 Python24.lib 文件) }}} 修正PythonXX.lib 方法如下:{{{ 1.拷贝python24.dll 到 C:\Python24\libs 目录下面 2.在命令行模式下,转到Python 的lib 目录下面 3.运行下面命令: pexports python24.dll >python24.def dlltool --dllname python24.dll --def python24.def --output-lib python24.lib |
坐以论道,起而行之,先写一个简单但完整的例子来测试pyrex调用已有lib库法。 环境:ubuntu 6.06,python 2.4.3 参考:http://ldots.org/pyrex-guide/ |
Line 28: | Line 23: |
Python24.dll 在 C:\WINNT\system32\python24.dll 下面。 }}} 上面的条件要先弄好才能开始玩,要不然别怪我教程不对。 |
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 静态库 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库是可以正常工作的 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了 安装: =>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} ) |
Line 33: | Line 93: |
=== 说明 === | =>python setup.py build_ext --inplace |
Line 35: | Line 95: |
只是编译有C++合成的项目不能用 setup.py 的方法,要手动编译: 假如我的pyrex 文件名是 test.pyx 像这样: |
测试: >>> import td >>> dir(td) ['__builtins__', '__doc__', '__file__', '__name__', 'tdadd'] >>> td.tdadd(1,2) 3 |
Line 38: | Line 102: |
python pyrexc test.pyx (pyrexc文件在 C:\Python24\scripts 下面,要把这个目录在环境变量里设一下。或是复制到你用的目录里) | 呵呵,OK了。 |
Line 40: | Line 104: |
g++ -c test.c -mno-cygwin -mdll -IC:\Python24\include g++ -mno-cygwin -shared -s test.o -LC:\Python24\libs -lpython24 -o test.pyd |
等会再试一试ctypes |
Line 43: | Line 106: |
就能通过编绎。 ==== C++ ==== 先编写一个C++文件: {{{#!c /////////////////////////////////////////////////////////////////// // in.h class AAA{ int num33; public: AAA(){ this->num33 = 10; } int getNum(){ return this->num33; } void setNum(int n222){ this->num33 = n222; } }; // 这是创造类的函数 AAA* NewAAA(){ return new AAA(); } // 这是析构函数 void DelAAA(void *o){ AAA* s = (AAA*)o; delete(s); } }}} ==== test.pyx ==== 再编写test.pyx 文件将类包含进来 {{{#!python # test.pyx # 通过 cdef extern 把类在头部声名一次 # 因为C++ class 与 struct 有兼容性所以把类当成 struct 就搞定 cdef extern from "in.h": ctypedef struct AAA: int (* getNum)() void (* setNum)(int n222) AAA* NewAAA() void DelAAA(void *o) cdef class PySomeClass: cdef AAA *thisptr def __new__(self): self.thisptr = NewAAA() def __dealloc__(self): DelAAA(self.thisptr) def getNum(self): return self.thisptr[0].getNum() def setNum(self,n): self.thisptr[0].setNum(n) }}} ==== 运行 ==== {{{ import test print test print dir(test) A = test.PySomeClass() A.setNum(99777) print A.getNum() }}} 输出: {{{ <module 'test' from 'D:\DTemp\PY__~1\test.pyd'> ['PySomeClass', '__builtins__', '__doc__', '__file__', '__name__'] 99777 }}} 现在基本上就算是研制成功了。。 === 主要原理 === Pyrex最初的设计主要是用来也C语言合成使用的工具,也只支持定义一个 struct 的外部声名。 但在Pyrex声名extern的东西就会原封不运的转换成 C 代码。 C++ 的 class 与 struct 其实是一回事情,在C++编译器与C 混合编译的时侯就一起编译了。 {{{ 欢迎Python 爱好者一起交流: 我的网名 ybeetle 电邮: [email protected] }}} 2006-08-17 |
Pyrex与C++混合编程 TableOfContents
综述
以前python想用C++混合编程只能通过 Boost 或 Swig 或是 DIY ,不过这三种方法都有些麻烦,不易控制与扩展。
其实高版本的Pyrex可以与C++混合编程,不过中文社区里好像没有介绍,这也是我写这篇教程的原因。
我的教程
ybeetle
060817分享
- 附件:教程所用代码下载 attachment:pyxx.rar
[:YbeetLeTryPyrex:快速尝试Pyrex和C++]
feihu
061206 列表分享
坐以论道,起而行之,先写一个简单但完整的例子来测试pyrex调用已有lib库法。 环境:ubuntu 6.06,python 2.4.3 参考:http://ldots.org/pyrex-guide/
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 静态库
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库是可以正常工作的
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了
安装: =>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"]) ],
)
=>python setup.py build_ext --inplace
测试: >>> import td >>> dir(td) ['builtins', 'doc', 'file', 'name', 'tdadd'] >>> td.tdadd(1,2) 3
呵呵,OK了。
等会再试一试ctypes