python高性能之路:使用C/C++編寫擴展

腳本語言通常使用c等靜態語言編寫擴展提升性能,下面使用cpp編寫一個實現兩數之和的python擴展函數html

完成案例代碼參考:1drv.ms/u/s!AquRvPz…python

構建python環境

減小擴展開發對系統python的影響,建議使用venv建立一個新的python開發環境ios

virtualenv ~/develop/venvpy3
複製代碼

操做效果以下 shell

-w482

使用命令source ~/develop/venvpy3/bin/activate激活便可api

建立擴展文件sumext.cpp

sumext.cpp函數

#include <iostream>
#include <stdio.h>
#include <Python.h>

using namespace std;
複製代碼

主要是引入依賴的Python.h文件頭便可,其它頭文件按需引入使用性能

實現兩數相加函數

static PyObject* sum(PyObject* Self, PyObject *args) {
    int a, b, s;
    if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
        return NULL;
    }

    s = a + b;

    return Py_BuildValue("i", s);
}
複製代碼

這個函數接受兩個int類型的參數,有一個int類型的返回值ui

函數參數解析

PyArg_ParseTuple將python腳本中傳入的參數解析爲cpp本地數據類型,i表示解析爲int類型,兩個i:"ii"表示有兩個int類型的參數spa

支持解析的數據類型列表參考:docs.python.org/3/c-api/arg…code

函數返回值定義

Py_BuildValue用於將cpp本地數據類型轉爲python腳本數據類型,i表示將cpp中int類型轉爲python腳本變量

支持解析的數據類型列表參考:docs.python.org/2.0/ext/bui…

定義函數爲python擴展函數

static PyMethodDef module_methods[] = {
    {"sum", (PyCFunction) sum, METH_VARARGS, NULL},
    {NULL, NULL, 0, NULL}
};
複製代碼

定義擴展基礎信息

static struct PyModuleDef sumext = {
    PyModuleDef_HEAD_INIT,
    "sumext",
    "extension for add two number",
    -1,
    module_methods
};
複製代碼

在擴展鉤子中註冊擴展&擴展函數

PyMODINIT_FUNC PyInit_sumext(void) {
    return PyModule_Create(&sumext);
}

PyMODINIT_FUNC PyInit_sum(void) {
    return PyModule_Create(&sumext);
}
複製代碼

格式:PyInit_模塊名/函數名 做用:python加載模塊/模塊函數時的初始化函數,能夠在模塊/函數初始化函數中執行自定義鉤子邏輯,最後返回擴展信息sumext便可

編譯擴展

setup.py:

from distutils.core import setup, Extension

setup(name='sumext', version='1.0', ext_modules=[Extension('sumext', ['sumext.cpp'])])
複製代碼

而後使用命令python setup.py install編譯,效果參考以下

-w810

使用擴展

action.py

import sumext

sum=sumext.sum(1, 2)

print("Sum is :", sum)
複製代碼

而後使用命令python action.py執行,執行效果以下:

-w336

能夠看到擴展已經成功加載執行了

參考資料

  1. docs.python.org/3/extending…
  2. docs.python.org/3/extending…
  3. www.tutorialspoint.com/python/pyth…
  4. docs.python.org/3/c-api/arg…
相關文章
相關標籤/搜索