参考

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混和编程中有说明,源码如下:

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Python.h> #define BUFSIZE 10 int fac(int n) {
if (n < )
return ;
return n * fac(n - );
} static PyObject * Extest_fac(PyObject *self, PyObject *args) {
int res;//计算结果值
int num;//参数
PyObject* retval;//返回值 //i表示需要传递进来的参数类型为整型,如果是,就赋值给num,如果不是,返回NULL;
res = PyArg_ParseTuple(args, "i", &num);
if (!res) {
//包装函数返回NULL,就会在Python调用中产生一个TypeError的异常
return NULL;
}
res = fac(num);
//需要把c中计算的结果转成python对象,i代表整数对象类型。
retval = (PyObject *)Py_BuildValue("i", res);
return retval;
} char *reverse(char *s) {
register char t;
char *p = s;
char *q = (s + (strlen(s) - ));
while (p < q) {
t = *p;
*p++ = *q;
*q-- = t;
}
return s;
} static PyObject *
Extest_reverse(PyObject *self, PyObject *args) {
char *orignal;
if (!(PyArg_ParseTuple(args, "s", &orignal))) {
return NULL;
}
return (PyObject *)Py_BuildValue("s", reverse(orignal));
} static PyObject *
Extest_doppel(PyObject *self, PyObject *args) {
char *orignal;
char *reversed;
PyObject * retval;
if (!(PyArg_ParseTuple(args, "s", &orignal))) {
return NULL;
}
retval = (PyObject *)Py_BuildValue("ss", orignal, reversed=reverse(strdup(orignal)));
free(reversed);
return retval;
} static PyMethodDef
ExtestMethods[] = {
{"fac", Extest_fac, METH_VARARGS},
{"doppel", Extest_doppel, METH_VARARGS},
{"reverse", Extest_reverse, METH_VARARGS},
{NULL, NULL},
}; void initExtest() {
Py_InitModule("Extest", ExtestMethods);
} int main() {
char s[BUFSIZE];
printf("4! == %d\n", fac());
printf("8! == %d\n", fac());
printf("12! == %d\n", fac());
strcpy(s, "abcdef");
printf("reversing 'abcdef', we get '%s'\n", reverse(s));
strcpy(s, "madam");
printf("reversing 'madam', we get '%s'\n", reverse(s));
return ;
}

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

正文

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

这里介绍两种方法:

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

拷贝:

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

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

 diff --git a/setup.py b/setup.py
index 81355c7..5083c3d
--- a/setup.py
+++ b/setup.py
@@ -, +, @@ class PyBuildExt(build_ext):
'-framework', 'Carbon']) ) + exts.append(Extension('Extest', ['Extest_wrap.c']))
self.extensions.extend(exts) # Call the method for detecting whether _tkinter can be compiled

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

 $ls build/lib.linux2-aarch64-2.7/Extest.so -l
-rwxrwxr-x pengdonglin pengdonglin Mar : build/lib.linux2-aarch64-2.7/Extest.so*

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

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

 [root@aarch64 root]# python
Python 2.7. (default, Mar , ::)
[GCC 4.9. (prerelease)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import Extest
>>> Extest.fac() >>> Extest.reverse("abc")
'cba'
>>> Extest.doppel("abc")
('abc', 'cba')
>>>

第二种: 手动编译

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

 #!/bin/bash
export PATH=/home/pengdonglin/src/qemu/aarch64/gcc-linaro-aarch64-linux-gnu-4.9-.07_linux/bin:$PATH 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" LDFLAGS="-L/home/pengdonglin/src/qemu/python_cross_compile/Python2/aarch64/lib -lpython2.7 -lpthread -ldl -lutil -lm -Xlinker -export-dynamic" aarch64-linux-gnu-gcc -c ../Extest_wrap.c ${CFLAGS} -o Extest.o aarch64-linux-gnu-gcc --shared Extest.o ${LDFLAGS} -o Extest.so

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

 $/usr/local/bin/python2-config --cflags
-I/usr/local/include/python2. -I/usr/local/include/python2. -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes $/usr/local/bin/python2-config --ldflags
-L/usr/local/lib/python2./config -lpython2. -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.
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./site-packages/ clean:
$(RM) *.o *.so .PHONY: clean all

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

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

这里也有三种方法:

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

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

 #!/bin/bash
CFLAGS="-I/home/pengdonglin/src/qemu/python_cross_compile/Python2/x86_64/include/python2.7 -fPIC" LDFLAGS="-L/home/pengdonglin/src/qemu/python_cross_compile/Python2/x86_64/lib -fPIC" gcc -c ../Extest_wrap.c ${CFLAGS} -o Extest.o gcc --shared Extest.o ${LDFLAGS} -o Extest.so

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

第三种:手动编写setup.py

setup.py:

 #!/usr/bin/env python

 from distutils.core import setup, Extension

 MOD = 'Extest_x86_64'
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. -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下面

 running install
running build
running build_ext
running install_lib
copying build/lib.linux-x86_64-2.7/Extest_x86_64.so -> /home/pengdonglin/src/qemu/python_cross_compile/Python2/x86_64/lib/python2./site-packages
running install_egg_info
Writing /home/pengdonglin/src/qemu/python_cross_compile/Python2/x86_64/lib/python2./site-packages/Extest_x86_64-0.0.-py2..egg-info

然后从新制作ramdisk就可以了

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

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

#!/bin/bash
../Python-2.7./configure
make -j8
sudo make install

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

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

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

 #!/bin/bash
CFLAGS="-I/usr/local/include/python2.7 -fPIC"
LDFLAGS="-L/usr/local/lib -fPIC"
gcc -c ../Extest_wrap.c ${CFLAGS} -o Extest.o
gcc --shared Extest.o ${LDFLAGS} -o Extest.so

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

测试:

 $sudo cp Extest.so /usr/local/lib/python2./site-packages/
$/usr/local/bin/python
Python 2.7. (default, Mar , ::)
[GCC 4.8.] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import Extest
>>> Extest.reverse("peng")
'gnep'

方法三: 编写setup.py

setup.py:

 $cat setup.py
#!/usr/bin/env python
from distutils.core import setup, Extension
MOD = 'Extest'
setup(name=MOD, ext_modules=[Extension(MOD, sources=['Extest_wrap.c'])])

编译:

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

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

 running build
running build_ext
building 'Extest' extension
creating build
creating build/temp.linux-x86_64-2.7
gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/usr/local/include/python2. -c Extest_wrap.c -o build/temp.linux-x86_64-2.7/Extest_wrap.o
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下面
 running install
running build
running build_ext
running install_lib
copying build/lib.linux-x86_64-2.7/Extest.so -> /usr/local/lib/python2./site-packages
running install_egg_info
Removing /usr/local/lib/python2./site-packages/Extest-0.0.-py2..egg-info
Writing /usr/local/lib/python2./site-packages/Extest-0.0.-py2..egg-info

用C扩展Python2的更多相关文章

  1. python基本数据类型以及基础运算符

    今日分享内容 作业讲解 python基本数据类型 与用户交互 格式化输出 基本运算符 多种赋值方式 逻辑运算符 成员运算符 分享内容详细 # 附加练习题(提示:一步步拆解) # 1.想办法打印出jas ...

  2. 灵活可扩展的工作流管理平台Airflow

    1. 引言 Airflow是Airbnb开源的一个用Python写就的工作流管理平台(workflow management platform).在前一篇文章中,介绍了如何用Crontab管理数据流, ...

  3. 使用c/c++扩展python

    用python脚本写应用比较方便,但有时候由于种种原因需要扩展python(比如给程序提供python接口等). 之前一直想整理下,今天终于坐下来把这件事情给做了,这里记录下,也方便我以后查阅. 说明 ...

  4. 基于Windows10 x64+visual Studio2013+Python2.7.12环境下的Caffe配置学习

    本文在windows下使用visual studio2013配置关联python(python-2.7.12.amd64.msi)的caffe项目,如果有耐心的人,当然可以自己去下载caffe项目自己 ...

  5. OpenStack 企业私有云的若干需求(2):自动扩展(Auto-scaling) 支持

    本系列会介绍OpenStack 企业私有云的几个需求: 自动扩展(Auto-scaling)支持 多租户和租户隔离 (multi-tenancy and tenancy isolation) 混合云( ...

  6. 机器学习常用Python扩展包

    在Ubuntu下安装Python模块通常有3种方法:1)使用apt-get:2)使用pip命令(推荐);3)easy_instal 可安装方法参考:[转]linux和windows下安装python集 ...

  7. 【转】Python3.x和Python2.x的区别

    这个星期开始学习Python了,因为看的书都是基于Python2.x,而且我安装的是Python3.1,所以书上写的地方好多都不适用于Python3.1,特意在Google上search了一下3.x和 ...

  8. Python和C扩展实现方法

    一.Python和C扩展 cPython是C编写的,python的扩展可以用C来写,也便于移植到C++. 编写的Python扩展,需要编译成一个.so的共享库. Python程序中. 官方文档:htt ...

  9. python2.x 默认编码问题

    python2.x中处理中文,是一件头疼的事情.网上写这方面的文章,测次不齐,而且都会有点错误,所以在这里打算自己总结一篇文章. 我也会在以后学习中,不断的修改此篇博客. 这里假设读者已有与编码相关的 ...

随机推荐

  1. kali的中文输入法-安装后无中文选项的解决办法

    我在我实体电脑上安装了kali 本想安装个中文输入法但是有时候输入发中根本没有选择输入法的这一项.所以导致很别扭,之前在虚机上安装过没有问题但是挪到实体机上就是没有用的也是fcitx,这一度让我这个小 ...

  2. readb(), readw(), readl(),writeb(), writew(), writel() 宏函数【转】

    转自:http://www.netfoucs.com/article/hustyangju/70429.html readb(), readw(), readl()函数功能:从内存映射的 I/O 空间 ...

  3. vue 数组

    今天项目中发现的一个问题: 在vue项目中输出一个数组,明明有俩个值:0,6,但是length为1 正常的是这样的 结果研究发现,是vue源码的问题,具体内容如下: 转载自:http://www.cn ...

  4. Java基础89 MySQL存储过程

    1.MySQL存储过程   1.1.什么是存储过程 带有逻辑的sql语句:带有流程控制语句(if  while)等等 的sql语句   1.2.存储过程的特点 1)执行效率非常快,存储过程是数据库的服 ...

  5. JAVA 基础基本语法---常量与变量

    JAVA 基础基本语法---常量与变量 语法:计算机能够识别的语言的规则: 0. 基本语法 编写Java程序时,应注意以下几点: 大小写敏感:Java是大小写敏感的,这就意味着标识符Hello与hel ...

  6. java 异常的限制

    一. 1.) 在覆盖方法的时候,只能抛出在基类方法的异常说明里列出的那些异常 2.) 在基类构造器声明的异常,在子类必须抛出,子类的构造器可以抛出任何异常,但是必须抛出基类构造器的异常 3.) 在基类 ...

  7. hdu 6118度度熊的交易计划(费用流)

    度度熊的交易计划 Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  8. js如何判断访问来源是来自搜索引擎(蜘蛛人)还是直接访问

    以下javascript脚本代码可以实现判断访问是否来自搜索引擎.代码如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <scri ...

  9. Java编程的逻辑 (35) - 泛型 (上) - 基本概念和原理

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  10. hdu 2519 求组合数

    求组合数 如果求C5 3 就是5*4*3/3*2*1 也就是(5/3)*(4/2)*(3/1) Sample Input5 //T3 2 //C3 25 34 43 68 0 Sample Outpu ...