用C扩展Python3

官方文档:

https://docs.python.org/3/extending/index.html

  • 交叉编译到aarch64上面

以交叉编译到aarch64上面为例,下面是Extest.c的实现:

 #include <Python.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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},
}; static struct PyModuleDef ExtestModule = {
PyModuleDef_HEAD_INIT,
"Extest",
NULL,
-,
ExtestMethods
}; PyMODINIT_FUNC PyInit_Extest(void)
{
return PyModule_Create(&ExtestModule);
}

采用手动编译, Makefile如下:

 CFLAGS = -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes
CFLAGS += -fPIC -I /home/pengdonglin/src/qemu/python_cross_compile/Python3/aarch64/include/python3.6m
CC = /home/pengdonglin/src/qemu/aarch64/gcc-linaro-aarch64-linux-gnu-4.9-.07_linux/bin/aarch64-linux-gnu-gcc all:Extest.so Extest.o: Extest.c
$(CC) $(CFLAGS) -c $^ -o $@ Extest.so: Extest.o
$(CC) -pthread -shared $^ -o $@
cp $@ /home/pengdonglin/src/qemu/python_cross_compile/Python3/aarch64/lib/python3./site-packages/ clean:
$(RM) *.o *.so .PHONY: clean all

执行make命令,就会在当前目录下生成一个Extest.so文件,然后将其放到板子上面的/usr/lib/python3.6/site-packages/下面即可

测试:

 [root@aarch64 root]# cp /mnt/Extest.so /usr/lib/python3./site-packages/
[root@aarch64 root]# python3
Python 3.6. (default, Mar , ::)
[GCC 4.9. (prerelease)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import Extest
>>> Extest.fac() >>> Extest.reverse("pengdonglin")
'nilgnodgnep'
>>> Extest.doppel("pengdonglin")
('pengdonglin', 'nilgnodgnep')
  • 编译到x86_64上面

编写setup.py如下:

 #/usr/bin/env python3

 from distutils.core import setup, Extension

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

编译

 $/usr/local/bin/python3 ./setup.py build
running build
running build_ext
building 'Extest' extension
creating build
creating build/temp.linux-x86_64-3.6
gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/usr/local/include/python3.6m -c Extest.c -o build/temp.linux-x86_64-3.6/Extest.o
creating build/lib.linux-x86_64-3.6
gcc -pthread -shared build/temp.linux-x86_64-3.6/Extest.o -o build/lib.linux-x86_64-3.6/Extest.cpython-36m-x86_64-linux-gnu.so

可以看到,在Python3上面用setup.py默认生成的so的名字是Extest.cpython-36m-x86_64-linux-gnu.so

安装

 $sudo /usr/local/bin/python3 ./setup.py install
[sudo] password for pengdonglin:
running install
running build
running build_ext
running install_lib
copying build/lib.linux-x86_64-3.6/Extest.cpython-36m-x86_64-linux-gnu.so -> /usr/local/lib/python3./site-packages
running install_egg_info
Writing /usr/local/lib/python3./site-packages/Extest-0.0.-py3..egg-info

可以看到,将Extest.cpython-36m-x86_64-linux-gnu.so拷贝到了/usr/local/lib/python3.6/site-packages下面。

测试

在PC上面输入python3命令:

 $python3
Python 3.6. (default, Mar , ::)
[GCC 4.8.] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import Extest
>>> Extest
<module 'Extest' from '/usr/local/lib/python3.6/site-packages/Extest.cpython-36m-x86_64-linux-gnu.so'>
>>> Extest.fac() >>> Extest.reverse("pengdonglin")
'nilgnodgnep'
>>> Extest.doppel("pengdonglin")
('pengdonglin', 'nilgnodgnep')
>>>

可以在第7行看到加载的Extest.so的路径,而且我们只需要import Extest就可以了。

完。

上一篇:epel安装第三方扩展源后,运行yum报错的解决方案


下一篇:<转+改>Web测试中关于登录的测试