免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 7183 | 回复: 6
打印 上一主题 下一主题

python核心编程学习笔记-怎样调用C语言编写的函数 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-07-25 19:34 |只看该作者 |倒序浏览
刚学习,模仿书上面练习了一下,传上来大家讨论

第22章  扩展Python

    本章主题
  引言/动机
  扩展Python
  创建应用程序代码
  用样板包装你的代码
  编译
  导入并测试
  引用计数
  线程和GIL
  相关话题

在本章中,我们将讨论如何编写扩展代码并将它们的功能整合到Python编程环境中来。首先我们会给出这样做的原因,然后一步步地教您如何做。应当指出的是,虽然大部分Python的扩展都是用C语言写的,并且下面的所有样例代码也都是由纯C语言写的,但请放心,这些代码很容易就可以移植到C++中。

[ 本帖最后由 MePython 于 2008-7-25 19:38 编辑 ]

22 .rar

520.46 KB, 下载次数: 258

原书章节:

论坛徽章:
0
2 [报告]
发表于 2008-07-25 19:39 |只看该作者
例22.1  纯C版本库(Extestl.c)
下面列出了我们想要包装并在Python解释器中使用的C函数的代码,main()是测试函数。


  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>

  4. int fac(int n)
  5. {
  6.     if (n < 2) return(1);   /* 0! == 1! == 1 */
  7.     return (n)*fac(n-1);    /* n! == n*(n-1)! */
  8. }

  9. char *reverse(char *s)
  10. {
  11.     register char t,            /* 中间变量t */
  12.     *p = s,                     /* fwd */
  13.     *q = (s + (strlen(s)-1));   /* bwd */

  14.     while (p < q)               /* if p < q */
  15.     {                           /*swap & mv ptrs */
  16.         t = *p;
  17.         *p++ = *q;
  18.         *q-- = t;
  19.     }
  20.     return s;
  21. }

  22. int main()
  23. {
  24.     char s[BUFSIZ];
  25.     printf("4! == %d\n", fac(4));
  26.     printf("8! == %d\n", fac(8));
  27.     printf("12! == %d\n", fac(12));
  28.     strcpy(s, "abcdef");
  29.     printf("reversing 'abcdef', we get '%s'\n", reverse(s));
  30.     strcpy(s, "madam");
  31.     printf("reversing 'madam', we get '%s'\n", reverse(s));
  32.     return 0;
  33. }
复制代码


编译运行:
zhou@zhou-desktop:~/Test$ gcc -o tt Extest1.c
zhou@zhou-desktop:~/Test$ ./tt
4! == 24
8! == 40320
12! == 479001600
reversing 'abcdef', we get 'fedcba'
reversing 'madam', we get 'madam'

[ 本帖最后由 MePython 于 2008-7-25 19:41 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2008-07-25 19:39 |只看该作者
22.2.2  用样板来包装你的代码
整个扩展的实现都是围绕着13.15.1节所说的“包装”这个概念进行的。你的设计要尽可能让你的实现语言与Python无缝结合。接口的代码被称为“样板”代码,它是你的代码与Python解释器之间进行交互所必不可少的一部分。
我们的样板主要分为4步。
1.包含Python的头文件。
2.为每个模块的每一个函数增加一个形如PyObject* Module_func()的包装函数。
3.为每个模块增加一个形如PyMethodDef ModuleMethods[]的数组。
4.增加模块初始化函数void initModule()。

论坛徽章:
0
4 [报告]
发表于 2008-07-25 19:40 |只看该作者
Extest2.c

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>

  4. int fac(int n)
  5. {
  6.     if (n < 2) return(1);
  7.     return (n)*fac(n-1);
  8. }

  9. char *reverse(char *s)
  10. {
  11.     register char t,
  12.     *p = s,
  13.     *q = ( s + ( strlen(s) - 1 ) );

  14.     while ( s && ( p < q ) )
  15.     {
  16.         t = *p;
  17.         *p++ = *q;
  18.         *q-- = t;
  19.     }
  20.     return s;
  21. }

  22. int test()
  23. {
  24.     char s[BUFSIZ];
  25.     printf("4! == %d\n", fac(4));
  26.     printf("8! == %d\n", fac(8));
  27.     printf("12! == %d\n", fac(12));
  28.     strcpy(s, "abcdef");
  29.     printf("reversing 'abcdef', we get '%s'\n", reverse(s));
  30.     strcpy(s, "madam");
  31.     printf("reversing 'madam', we get '%s'\n", reverse(s));
  32.     return 0;
  33. }

  34. #include "Python.h"

  35. static PyObject *
  36. Extest_fac( PyObject *self, PyObject *args )
  37. {
  38.     int num;
  39.     if ( !PyArg_ParseTuple(args, "i", &num) )
  40.     {
  41.         return NULL;
  42.     }
  43.     return (PyObject*)Py_BuildValue( "i", fac(num) );
  44. }

  45. static PyObject *
  46. Extest_doppel( PyObject *self, PyObject *args )
  47. {
  48.     char *orig_str;
  49.     char *dupe_str;
  50.     PyObject* retval;

  51.     if ( !PyArg_ParseTuple(args, "s", &orig_str) )
  52.     {
  53.         return NULL;
  54.     }
  55.     retval = (PyObject*)Py_BuildValue( "ss", orig_str, \
  56.              dupe_str = reverse(strdup(orig_str)) );
  57.     free(dupe_str);
  58.     return retval;
  59. }

  60. static PyObject *
  61. Extest_test(PyObject *self, PyObject *args)
  62. {
  63.     test();
  64.     return (PyObject*)Py_BuildValue("");
  65. }

  66. static PyMethodDef
  67. ExtestMethods[] =
  68. {
  69.     { "fac",    Extest_fac,    METH_VARARGS },
  70.     { "doppel", Extest_doppel, METH_VARARGS },
  71.     { "test",   Extest_test,   METH_VARARGS },
  72.     { NULL, NULL },
  73. };

  74. void initExtest()
  75. {
  76.     Py_InitModule("Extest", ExtestMethods);
  77. }
复制代码


编译运行(有警告,暂时忽略 ):
zhou@zhou-desktop:~/Test$ python setup.py build
running build
running build_ext
building 'Extest' extension
creating build
creating build/temp.linux-i686-2.5
gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.5 -c Extest2.c -o build/temp.linux-i686-2.5/Extest2.o
Extest2.c:27: 警告: 函数声明不是一个原型
Extest2.c:86: 警告: 函数声明不是一个原型
creating build/lib.linux-i686-2.5
gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions build/temp.linux-i686-2.5/Extest2.o -o build/lib.linux-i686-2.5/Extest.so

[ 本帖最后由 MePython 于 2008-7-25 19:46 编辑 ]

论坛徽章:
0
5 [报告]
发表于 2008-07-25 19:40 |只看该作者
22.2.3  编译
现在,我们已经到了编译阶段。为了让你的新Python扩展能被创建,你需要把它们与Python库放在一起编译。现在已经有了一套跨30多个平台的规范,它极大地方便了编写扩展的人。distutils包被用来编译、安装和分发这些模块、扩展和包。这个模块在Python2.0的时候就已经出现了,并用于代替1.x版本时的用Makefile来编译扩展的方法。使用distutils包的时候我们可以方便地按以下步骤来做:
1.创建 setup.py;
2.通过运行setup.py来编译和连接您的代码;
3.从Python中导入您的模块;
4.测试功能。

zhou@zhou-desktop:~/Test$ python setup.py install
running install
running build
running build_ext
running install_lib
copying build/lib.linux-i686-2.5/Extest.so -> /usr/lib/python2.5/site-packages
error: /usr/lib/python2.5/site-packages/Extest.so: Permission denied
zhou@zhou-desktop:~/Test$ sudo python setup.py install
[sudo] password for zhou:
running install
running build
running build_ext
running install_lib
copying build/lib.linux-i686-2.5/Extest.so -> /usr/lib/python2.5/site-packages
running install_egg_info
Writing /usr/lib/python2.5/site-packages/Extest-0.0.0.egg-info

[ 本帖最后由 MePython 于 2008-7-25 19:48 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2008-07-25 19:45 |只看该作者
测试:
zhou@zhou-desktop:~/Test$ python
Python 2.5.2 (r252:60911, Apr 21 2008, 11:12:42)
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import Extest
>>> Extest.fac(5)
120
>>> Extest.fac(3)
6

待会再改成C++的看看是不是一样的,刚开始找书上弄,简单了点

将一处加上cout打印一个string类型,编译安装都没有问题,就是测试运行时出错:
import Extest
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: dynamic module does not define init function (initExtest)
有空再看,先游戏去。

[ 本帖最后由 MePython 于 2008-7-25 20:08 编辑 ]

论坛徽章:
0
7 [报告]
发表于 2008-07-28 15:41 |只看该作者
支持,强顶.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP