热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

用C扩展Python2

python扩展实现方法--python与c混和编程编写Python扩展(ExtendingPythonwithCorC++)https:docs.python.org2.7ext

python

python扩展实现方法--python与c混和编程

编写Python扩展(Extending Python with C or C++)

https://docs.python.org/2.7/extending/embedding.html

环境

主机: ubuntu14.04 64bit

开发板: qemu + aarch64 (参考: http://www.cnblogs.com/pengdonglin137/p/6442583.html)

 

工具链: aarch64-linux-gnu-gcc  (gcc version 4.9.1 20140529)

Python版本: Python-2.7.13

 

概述

上面参考列表中的文章已经说的很全了,这里仅作一些补充。分为三个:

1、交叉编译扩展模块到aarch64上面

2、编译扩展模块到Qemu模拟的x86_64上面

3、编译扩展模块到PC(x86_64)上面

采用的测试模块是Extend_wrap.c,这个在python扩展实现方法--python与c混和编程中有说明,源码如下:

1 #include

2 #include

3 #include

4 #include

5

6 #define BUFSIZE 10

7

8 int fac(int n) {

9 if (n <2)

10 return 1;

11 return n * fac(n - 1);

12 }

13

14 static PyObject * Extest_fac(PyObject *self, PyObject *args) {

15 int res;//计算结果值

16 int num;//参数

17 PyObject* retval;//返回值

18

19 //i表示需要传递进来的参数类型为整型,如果是,就赋值给num,如果不是,返回NULL;

20 res = PyArg_ParseTuple(args, "i", &num);

21 if (!res) {

22 //包装函数返回NULL,就会在Python调用中产生一个TypeError的异常

23 return NULL;

24 }

25 res = fac(num);

26 //需要把c中计算的结果转成python对象,i代表整数对象类型。

27 retval = (PyObject *)Py_BuildValue("i", res);

28 return retval;

29 }

30

31 char *reverse(char *s) {

32 register char t;

33 char *p = s;

34 char *q = (s + (strlen(s) - 1));

35 while (p

36 t = *p;

37 *p++ = *q;

38 *q-- = t;

39 }

40 return s;

41 }

42

43 static PyObject *

44 Extest_reverse(PyObject *self, PyObject *args) {

45 char *orignal;

46 if (!(PyArg_ParseTuple(args, "s", &orignal))) {

47 return NULL;

48 }

49 return (PyObject *)Py_BuildValue("s", reverse(orignal));

50 }

51

52 static PyObject *

53 Extest_doppel(PyObject *self, PyObject *args) {

54 char *orignal;

55 char *reversed;

56 PyObject * retval;

57 if (!(PyArg_ParseTuple(args, "s", &orignal))) {

58 return NULL;

59 }

60 retval = (PyObject *)Py_BuildValue("ss", orignal, reversed=reverse(strdup(orignal)));

61 free(reversed);

62 return retval;

63 }

64

65 static PyMethodDef

66 ExtestMethods[] = {

67 {"fac", Extest_fac, METH_VARARGS},

68 {"doppel", Extest_doppel, METH_VARARGS},

69 {"reverse", Extest_reverse, METH_VARARGS},

70 {NULL, NULL},

71 };

72

73 void initExtest() {

74 Py_InitModule("Extest", ExtestMethods);

75 }

76

77 int main() {

78 char s[BUFSIZE];

79 printf("4! == %d\n", fac(4));

80 printf("8! == %d\n", fac(8));

81 printf("12! == %d\n", fac(12));

82 strcpy(s, "abcdef");

83 printf("reversing 'abcdef', we get '%s'\n", reverse(s));

84 strcpy(s, "madam");

85 printf("reversing 'madam', we get '%s'\n", reverse(s));

86 return 0;

87 }

关于这段代码的解释,请参考python扩展实现方法--python与c混和编程

正文

1、交叉编译扩展模块到aarch64上面

这里介绍两种方法:

第一种: 将这个文件拷贝到Python2.7.3的Modules目录下面编译

拷贝:

cp Extest_wrap.c ../../Python-2.7.13/Modules/

修改Python-2.7.13/setup.py,添加模块:

1 diff --git a/setup.py b/setup.py

2 index 81355c7..5083c3d 100644

3 --- a/setup.py

4 +++ b/setup.py

5 @@ -1743,6 +1743,7 @@ class PyBuildExt(build_ext):

6 '-framework', 'Carbon']) )

7

8

9 + exts.append(Extension('Extest', ['Extest_wrap.c']))

10 self.extensions.extend(exts)

11

12 # Call the method for detecting whether _tkinter can be compiled

然后执行aarch64/mk2_make.sh,可以看到build/lib.linux2-aarch64-2.7/下面已经有Extest.so了:

1 $ls build/lib.linux2-aarch64-2.7/Extest.so -l

2 -rwxrwxr-x 1 pengdonglin pengdonglin 22121 Mar 22 14:47 build/lib.linux2-aarch64-2.7/Extest.so*

然后执行aarch64/mk3_install.sh,就会将Extest.so安装到lib/python2.7/lib-dynload/下面。

最后重新制作ramdisk文件,重启板子,测试Extest.so能否使用:

1 [root@aarch64 root]# python

2 Python 2.7.13 (default, Mar 22 2017, 10:39:43)

3 [GCC 4.9.1 20140529 (prerelease)] on linux2

4 Type "help", "copyright", "credits" or "license" for more information.

5 >>> import Extest

6 >>> Extest.fac(4)

7 24

8 >>> Extest.reverse("abc")

9 'cba'

10 >>> Extest.doppel("abc")

11 ('abc', 'cba')

12 >>>

第二种: 手动编译

我们需要指定编译用的库以及头文件的搜索路径即可,下面是编译命令:

1 #!/bin/bash

2 export PATH=/home/pengdonglin/src/qemu/aarch64/gcc-linaro-aarch64-linux-gnu-4.9-2014.07_linux/bin:$PATH

3

4 CFLAGS="-I/home/pengdonglin/src/qemu/python_cross_compile/Python2/aarch64/include/python2.7 -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes"

5

6 LDFLAGS="-L/home/pengdonglin/src/qemu/python_cross_compile/Python2/aarch64/lib -lpython2.7 -lpthread -ldl -lutil -lm -Xlinker -export-dynamic"

7

8 aarch64-linux-gnu-gcc -c ../Extest_wrap.c ${CFLAGS} -o Extest.o

9

10 aarch64-linux-gnu-gcc --shared Extest.o ${LDFLAGS} -o Extest.so

其中CFLAGS和LDFLAGS的值可以用下面的命令获得

1 $/usr/local/bin/python2-config --cflags

2 -I/usr/local/include/python2.7 -I/usr/local/include/python2.7 -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes

3

4 $/usr/local/bin/python2-config --ldflags

5 -L/usr/local/lib/python2.7/config -lpython2.7 -lpthread -ldl -lutil -lm -Xlinker -export-dynamic

然后编译,就会在当前目录下面生成一个Extest.so,然后拷贝到板子的/usr/lib/python2.7/site-packages/下面,这个目录下存放的是一些第三方的扩展模块,而/usr/lib/python2.7/lib-dynload/存放的一般是内建模块。

或者可以写成Makefile:

CFLAGS = -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes

CFLAGS += -fPIC -I/home/pengdonglin/qemu/thiry_part/Python2/aarch32/include/python2.7

CC = arm-none-linux-gnueabi-gcc

all:Extest.so

Extest.o: Extest_wrap.c

$(CC) $(CFLAGS) -c $^ -o $@

Extest.so: Extest.o

$(CC) -pthread -shared $^ -o $@

cp $@ /home/pengdonglin/qemu/thiry_part/Python2/aarch32/lib/python2.7/site-packages/

clean:

$(RM) *.o *.so

.PHONY: clean all

将Extest_wrap.c跟Makefile放到统一目录下执行make命令即可

2、编译扩展模块到Qemu模拟的x86_64上面

这里也有三种方法:

第一种:将Extend_wrap.c拷贝到Python源码的Modules目录下,这个前面说过,不再重复

第二种:手动编译,编译命令如下

1 #!/bin/bash

2 CFLAGS="-I/home/pengdonglin/src/qemu/python_cross_compile/Python2/x86_64/include/python2.7 -fPIC"

3

4 LDFLAGS="-L/home/pengdonglin/src/qemu/python_cross_compile/Python2/x86_64/lib -fPIC"

5

6 gcc -c ../Extest_wrap.c ${CFLAGS} -o Extest.o

7

8 gcc --shared Extest.o ${LDFLAGS} -o Extest.so

编译完成后,将Extest.so拷贝到板子上面的相应目录下即可(如/usr/lib/python2.7/site-packages)

第三种:手动编写setup.py

setup.py:

1 #!/usr/bin/env python

2

3 from distutils.core import setup, Extension

4

5 MOD = 'Extest_x86_64'

6 setup(name=MOD, ext_modules=[Extension(MOD, sources=['Extest_wrap.c'])])

这里模块名是Extest_x86_64,同时需要注意的是需要将setup.py跟Extest_wrap.c放到同一个目录下面。

编译:

/home/pengdonglin/src/qemu/python_cross_compile/Python2/x86_64/bin/python ./setup.py build

从log看执行的其实就是下面两条命令:

gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/home/pengdonglin/src/qemu/python_cross_compile/Python2/x86_64/include/python2.7 -c Extest_wrap.c -o build/temp.linux-x86_64-2.7/Extest_wrap.o

creating build/lib.linux-x86_64-2.7

gcc -pthread -shared build/temp.linux-x86_64-2.7/Extest_wrap.o -o build/lib.linux-x86_64-2.7/Extest_x86_64.so

安装:

/home/pengdonglin/src/qemu/python_cross_compile/Python2/x86_64/bin/python ./setup.py install

从log看,Extest_x86_64.so会被安装到/home/pengdonglin/src/qemu/python_cross_compile/Python2/x86_64/lib/python2.7/site-packages下面

1 running install

2 running build

3 running build_ext

4 running install_lib

5 copying build/lib.linux-x86_64-2.7/Extest_x86_64.so -> /home/pengdonglin/src/qemu/python_cross_compile/Python2/x86_64/lib/python2.7/site-packages

6 running install_egg_info

7 Writing /home/pengdonglin/src/qemu/python_cross_compile/Python2/x86_64/lib/python2.7/site-packages/Extest_x86_64-0.0.0-py2.7.egg-info

然后从新制作ramdisk就可以了

3、编译扩展模块到PC(x86_64)上面

在操作之前PC上面应该用Python源码编译安装一次,方法很简单:

#!/bin/bash

../Python-2.7.13/configure

make -j8

sudo make install

默认会被安装到/usr/local下面

方法一: 将Extend_wrap.c拷贝到Python源码的Modules目录下,这个前面说过,不再重复

方法二: 手动编译,编译命令如下

1 #!/bin/bash

2 CFLAGS="-I/usr/local/include/python2.7 -fPIC"

3 LDFLAGS="-L/usr/local/lib -fPIC"

4 gcc -c ../Extest_wrap.c ${CFLAGS} -o Extest.o

5 gcc --shared Extest.o ${LDFLAGS} -o Extest.so

将生成的Extest.so拷贝到/usr/local/lib/python2.7/site-packages/即可

测试:

1 $sudo cp Extest.so /usr/local/lib/python2.7/site-packages/

2 $/usr/local/bin/python

3 Python 2.7.13 (default, Mar 22 2017, 13:18:43)

4 [GCC 4.8.4] on linux2

5 Type "help", "copyright", "credits" or "license" for more information.

6 >>> import Extest

7 >>> Extest.reverse("peng")

8 'gnep'

方法三: 编写setup.py

setup.py:

1 $cat setup.py

2 #!/usr/bin/env python

3 from distutils.core import setup, Extension

4 MOD = 'Extest'

5 setup(name=MOD, ext_modules=[Extension(MOD, sources=['Extest_wrap.c'])])

编译:

/usr/local/bin/python ./setup.py build

从log看,执行的是下面的命令:

1 running build

2 running build_ext

3 building 'Extest' extension

4 creating build

5 creating build/temp.linux-x86_64-2.7

6 gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/usr/local/include/python2.7 -c Extest_wrap.c -o build/temp.linux-x86_64-2.7/Extest_wrap.o

7 gcc -pthread -shared build/temp.linux-x86_64-2.7/Extest_wrap.o -o build/lib.linux-x86_64-2.7/Extest.so

安装:

sudo /usr/local/bin/python ./setup.py install

从log看,Extest.so被安装到了/usr/local/lib/python2.7/site-packages下面

1 running install

2 running build

3 running build_ext

4 running install_lib

5 copying build/lib.linux-x86_64-2.7/Extest.so -> /usr/local/lib/python2.7/site-packages

6 running install_egg_info

7 Removing /usr/local/lib/python2.7/site-packages/Extest-0.0.0-py2.7.egg-info

8 Writing /usr/local/lib/python2.7/site-packages/Extest-0.0.0-py2.7.egg-info


推荐阅读
  • 为什么Python2更新到Python3这么慢
    这篇文章主要介绍为什么Python2更新到Python3这么慢,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!作为目前最为流行的编程 ... [详细]
  • Python2.7是一款非常好用的编程语言,此版本与相比于3.x版本相比更加成熟一些,支持的第三方类库、相关资料也是最多的,非常适合于Python开发人员进行使用,尤其是新入门的朋 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文介绍了包的基础知识,包是一种模块,本质上是一个文件夹,与普通文件夹的区别在于包含一个init文件。包的作用是从文件夹级别组织代码,提高代码的维护性。当代码抽取到模块中后,如果模块较多,结构仍然混乱,可以使用包来组织代码。创建包的方法是右键新建Python包,使用方式与模块一样,使用import来导入包。init文件的使用是将文件夹变成一个模块的方法,通过执行init文件来导入包。一个包中通常包含多个模块。 ... [详细]
  • python2写入文件乱码怎么解决?[python常见问题]
    ​python写入中文乱码的解决方法:1、写入的文件名乱码可以使用unicode()函数编码来解决。2、在写入文件时在创建文件语句后使用f.write(codecs.BOM_ ... [详细]
  • 提升Python编程效率的十点建议
    本文介绍了提升Python编程效率的十点建议,包括不使用分号、选择合适的代码编辑器、遵循Python代码规范等。这些建议可以帮助开发者节省时间,提高编程效率。同时,还提供了相关参考链接供读者深入学习。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • Python2中出现中文报错如何解决
    Python2中出现中文报错如何解决?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易 ... [详细]
  •     来,这次我们就看下Python模块(Module)。它是一个Python文件,以.py结尾,包含了Python对象定义和Python语句。模块让你能够有逻辑地组织你的Pyt ... [详细]
  • 安装必要的库,针对centos是minimal安装yuminstallzlib-develbzip2-developenssl-develncurses-develsqlite-develreadline-develtk-develgc ... [详细]
  • 农历五月初一宜声明变量"a",提交代码;忌打DOTA,提交BUG适宜方位:坐西朝东多饮水、鲜奶,女神亲近指数较高进入正题本节内容如下:什么是IO文件内容操作操作文本文件操作二进制文 ... [详细]
author-avatar
寻找初心
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有