zoukankan      html  css  js  c++  java
  • python的C扩展调用,使用原生的python-C-Api

    1、在文件第一行包含python调用扩展的头文件

    #include <Python.h>

    2、用原生C写好需要调用的函数

    int add_one(int a){
        return a + 1;      
    }

    3、用python规定的调用方式,加一层C语言的包装,包装内容包括

      a.定义一个新的静态函数,接受两个PyObject *参数,返回一个PyObject *值

      b.解析第二个输入的PyObject *(通过PyArg_ParseTuple等方法),把python输入的变量变成C的变量

      c.调用原生C函数

      d.将调用返回的C变量,转换为PyObject*或其子类(通过PyLong_FromLong)等方法,并返回

    static PyObject * py_add_one(PyObject *self, PyObject *args){
        int num;
        if (!PyArg_ParseTuple(args, "i", &num)) return NULL;
        return PyLong_FromLong(add_one(num));
    }

    4、创建一个数组,来指明python可调用这个扩展的函数。

    其中"add_one",代表编译后python调用时希望使用的函数名,

    py_add_one,代表调用当前C代码中的哪个函数,

    METH_VARARGS,代表函数的参数传递形式,主要包括位置参数和关键字参数两种,

    关于这个变量具体参考https://docs.python.org/3/extending/extending.html的1.4节。

    如果希望添加新的函数,则在最后的{NULL, NULL}之前按同样格式填写新的调用信息。

    static PyMethodDef Methods[] = {
        {"add_one", py_add_one, METH_VARARGS}, 
        {NULL, NULL}
    };

    5、创建module的信息,包括了python调用时的模块名、可调用的函数集(就是上一步定义的Methods)等信息

    static struct PyModuleDef cModule = {
        PyModuleDef_HEAD_INIT,
        "Test", /*module name*/
        "", /* module documentation, may be NULL */
        -1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
        Methods
    };

    6、module初始化

     PyMODINIT_FUNC PyInit_Test(void){ return PyModule_Create(&cModule);}

    7、写一个setup.py脚本,使用distutils包作为包构建安装的工具

    from distutils.core import setup, Extension
    module1 = Extension('Test', sources = ['add.c'])
    setup (name = 'Test',
           version = '1.0',
           description = 'This is a demo package',
           ext_modules = [module1])

    8、调用setup.py,python setup.py build可以编译代码,python setup.py install可以编译代码并直接将包放入当前python环境的包的路径以供调用。

    非常需要注意的是,python 3.5版本以后,windows平台下python的C/C++扩展不再支持gcc的编译,并强制要求使用msvc进行编译

    所以python setup.py build编译出来的结果无法正常使用,需使用

    python setup.py build --compiler msvc

    当需要安装时,则

    python setup.py build --compiler msvc install

    关于此情况的参考:

    https://stackoverflow.com/questions/16737260/how-to-tell-distutils-to-use-gcc

    https://stackoverflow.com/questions/3297254/how-to-use-mingws-gcc-compiler-when-installing-python-package-using-pip

    9、测试安装好的C扩展

    import Test as t
    x = 1
    print(t.add_one(x))

    附C文件完整代码

    #include <Python.h>
    
    int add_one(int a){
        return a + 1;      
    }
    
    static PyObject * py_add_one(PyObject *self, PyObject *args){
        int num;
        if (!PyArg_ParseTuple(args, "i", &num)) return NULL;
        return PyLong_FromLong(add_one(num));
    }
    
    static PyMethodDef Methods[] = {
        {"add_one", py_add_one, METH_VARARGS}, 
        {NULL, NULL}
    };
    
    static struct PyModuleDef cModule = {
        PyModuleDef_HEAD_INIT,
        "Test", /*module name*/
        "", /* module documentation, may be NULL */
        -1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
        Methods
    };
    
    PyMODINIT_FUNC PyInit_Test(void){ return PyModule_Create(&cModule);}

     https://segmentfault.com/a/1190000000479951

  • 相关阅读:
    设计模式(观察者模式,MVC模式)
    设计模式(单例,委托模式)
    iOS API
    iOS介绍
    多种服饰颜色搭配
    国内npm镜像使用
    iOS开发拓展篇—应用之间的跳转和数据传
    iOS开发网络篇—使用ASI框架进行文件下载
    iOS开发网络篇—数据缓存(使用NSURLCache)
    iOS开发网络篇—发送json数据给服务器以及多值参数
  • 原文地址:https://www.cnblogs.com/catnip/p/8329298.html
Copyright © 2011-2022 走看看