zoukankan      html  css  js  c++  java
  • 用C扩展Python3

    官方文档:

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

    • 交叉编译到aarch64上面

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

     1 #include <Python.h>
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 #include <string.h>
     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 < q) {
    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 static struct PyModuleDef ExtestModule = {
    74     PyModuleDef_HEAD_INIT,
    75     "Extest",
    76     NULL,
    77     -1,
    78     ExtestMethods
    79 };
    80 
    81 PyMODINIT_FUNC PyInit_Extest(void)
    82 {
    83     return PyModule_Create(&ExtestModule);
    84 }

    采用手动编译, Makefile如下:

     1 CFLAGS = -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes
     2 CFLAGS += -fPIC -I /home/pengdonglin/src/qemu/python_cross_compile/Python3/aarch64/include/python3.6m
     3 CC = /home/pengdonglin/src/qemu/aarch64/gcc-linaro-aarch64-linux-gnu-4.9-2014.07_linux/bin/aarch64-linux-gnu-gcc
     4 
     5 all:Extest.so
     6 
     7 Extest.o: Extest.c
     8     $(CC) $(CFLAGS) -c $^ -o $@
     9 
    10 Extest.so: Extest.o
    11     $(CC) -pthread -shared $^ -o $@
    12     cp $@ /home/pengdonglin/src/qemu/python_cross_compile/Python3/aarch64/lib/python3.6/site-packages/
    13 
    14 clean:
    15     $(RM) *.o *.so
    16 
    17 .PHONY: clean all

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

    测试:

     1 [root@aarch64 root]# cp /mnt/Extest.so /usr/lib/python3.6/site-packages/
     2 [root@aarch64 root]# python3
     3 Python 3.6.0 (default, Mar 23 2017, 10:54:13) 
     4 [GCC 4.9.1 20140529 (prerelease)] on linux
     5 Type "help", "copyright", "credits" or "license" for more information.
     6 >>> import Extest
     7 >>> Extest.fac(4)
     8 24
     9 >>> Extest.reverse("pengdonglin")
    10 'nilgnodgnep'
    11 >>> Extest.doppel("pengdonglin")
    12 ('pengdonglin', 'nilgnodgnep')
    • 编译到x86_64上面

    编写setup.py如下:

    1 #/usr/bin/env python3
    2 
    3 from distutils.core import setup, Extension
    4 
    5 MOD = 'Extest'
    6 setup(name=MOD, ext_modules=[Extension(MOD, sources=['Extest.c'])])

    编译

    1 $/usr/local/bin/python3 ./setup.py build
    2 running build
    3 running build_ext
    4 building 'Extest' extension
    5 creating build
    6 creating build/temp.linux-x86_64-3.6
    7 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
    8 creating build/lib.linux-x86_64-3.6
    9 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

    安装

    1 $sudo /usr/local/bin/python3 ./setup.py install
    2 [sudo] password for pengdonglin: 
    3 running install
    4 running build
    5 running build_ext
    6 running install_lib
    7 copying build/lib.linux-x86_64-3.6/Extest.cpython-36m-x86_64-linux-gnu.so -> /usr/local/lib/python3.6/site-packages
    8 running install_egg_info
    9 Writing /usr/local/lib/python3.6/site-packages/Extest-0.0.0-py3.6.egg-info

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

    测试

    在PC上面输入python3命令:

     1 $python3
     2 Python 3.6.0 (default, Mar 23 2017, 10:40:28) 
     3 [GCC 4.8.4] on linux
     4 Type "help", "copyright", "credits" or "license" for more information.
     5 >>> import Extest
     6 >>> Extest
     7 <module 'Extest' from '/usr/local/lib/python3.6/site-packages/Extest.cpython-36m-x86_64-linux-gnu.so'>
     8 >>> Extest.fac(4)
     9 24
    10 >>> Extest.reverse("pengdonglin")
    11 'nilgnodgnep'
    12 >>> Extest.doppel("pengdonglin")
    13 ('pengdonglin', 'nilgnodgnep')
    14 >>> 

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

    完。

  • 相关阅读:
    计数和查找
    遍历
    top小火箭
    leetcode 字符串中的第一个唯一字符
    leetcode 颠倒整数
    leetcode 反转字符串
    leetcode 有效的数独
    leetcode 两数之和
    leetcode 移动零
    leetcode 加一
  • 原文地址:https://www.cnblogs.com/pengdonglin137/p/6605046.html
Copyright © 2011-2022 走看看