Cとの組み合わせでPython言語の拡張機能

ディレクトリ

 

1. Pythonの/ CのAPI

1.1導入はPython.h

1.2パッケージング機能

1.3免責事項リストモジュールのメソッド

1.4モジュール構成定義されました

1.5定义モジュールの初期化メソッド

1.6拡張モジュールを確立

2.のctypes

プログラムの2.1 C言語のバージョン

共有ライブラリの2.2設立

2.3導入ライブラリ

3. SWIG

C言語プログラムのバージョン3.1を作成します。

3.2インターフェイスファイルを確立

3.3は、ラッパーファイルを生成します

3.4共有ライブラリの構築


1. Pythonの/ CのAPI

最初のPython / C APIによって達成するための最も基本的な方法を導入しました。

Python拡張モジュールを確立し、公式のPythonモジュールはPython以外のPython言語であるとの通話は、公式文書は、アドレスすることができます:... docs.python.org/3/extendingを、あなたがC拡張を書いている時点で、すべての私が読むことをお勧めします。

まず、PythonのFeibolaqiのバージョンをお見せします

def fib_recursive(n):
    if n < 2:
        return n
    return fib_recursive(n - 1) + fib_recursive(n - 2)
    
start_ts = time.time()
print(fib_recursive(35))
print(time.time() - start_ts)

# 运行结果:
# 9227465
# 3.8501219749450684
复制代码

このプログラムは、C言語プログラムに変更指名された場合にspeedup_fib.c書き直すことにする方法は、次の手順が必要です。

1.1導入はPython.h

パイソン/ CのAPIは、はPython.hヘッダファイルを導入する必要がありますC言語のビルドPython拡張モジュールの石炭の紹介です。

// content of speedup_fib.c
#include <Python.h>

long long _fib(long long n){
    if(n < 2)
        return n;
    else
        return _fib(n-1) + _fib(n-2);
};
复制代码

導入Python.hC. Feibolaqiの、書かれた言語バージョン

1.2パッケージング機能

C言語に対応するPythonのオブジェクト内のすべてがあるPyObject本来の機能をパッケージにして、およびパラメータと戻り値があるしましょうPyObject

公式の形式は、次の3つのパラメータが用意されています。

  • (PyObject *自己)
  • (PyObject *自己、PyObject * argsを)
  • (PyObject *自己、PyObject * argsを、PyObject * kwargsから)

引数は位置引数を表し、kwargsからはキーワード引数です。

パラメータの独自の定義にC言語でのPython置くこれらの引数は、その後も、いくつかのAPIを呼び出して、具体的公式ドキュメントを参照する必要がdocs.python.org/3/c-api/arg ...下のスクリーンショット。

 

 

 

共通するのは、2です。

  • int型はPyArg_ParseTuple(PyObject * argsを、constのchar型*形式、...)
  • int型PyArg_ParseTupleAndKeywords(PyObject * argsを、PyObject *はキロワット、constのchar型*フォーマット、CHAR *キーワード[]、...)

従来の位置引数、第二の処理テープ位置引数とキーワード引数で最初の処置。

前記formatフォーマットされたパラメータ、整数や文字列の長さと種類、特に公式ドキュメントを参照してください。docs.python.org/2.0/ext/par ...

プログラムは、主要なパラメータをFeibolaqiないので、最初の関数とパラメータの使用は、長い整数をフォーマットする必要があるため、長整数クエリ文書はさl表現します。

上記の説明によると、最後のラッパの後です。

// content of speedup_fib.c
static PyObject *fib(PyObject *self, PyObject *args) {

   long long n; // 定义 参数

   long long res; // 定义返回值
   
   // 将参数进行包装,并格式化为长整型l,如果包装失败,则返回NULL.
   if (!PyArg_ParseTuple(args, "l", &n))
       return NULL;
   // 调用C语言版本的斐波拉契,同时传入包装好的参数n
   res = _fib(n);
   // 将返回值用  Py_BuildValue 包成 PyObject 传给 Python
   return Py_BuildValue("l", res);
};
复制代码

Feibolaqi機能がパッケージとして定義されfib、そして最終的には値も、戻り値はC言語にパックされてパックする必要が戻りますPyObject

1.3免責事項リストモジュールのメソッド

機能モジュールはこのリストメソッドモジュールを確立するために、一枚ずつ包装された後、目的は、入力フォーマットの形と機能であるC言語の各機能と機能の間のパッケージの対応関係を宣言することです。

{name, method, flags, doc}
即 {名称,包装函数,哪种argument形式, 描述}
复制代码

アイデンティティのフラグは、公式ドキュメントを参照することができますdocs.python.org/3/c-api/str ...

以上が、それぞれMETH_VARARGSとMETH_KEYWORDS、引数およびキーワードです。

したがって、上記の説明モジュールの方法に従って、次のように定義されます。

// content of speedup_fib.c
static PyMethodDef SpeedupFibMethods[] = {
    {"speedup_fib", (PyCFunction) fib, METH_VARARGS, "fast fib"},
    {NULL, NULL, 0, NULL} // 以 NULL 作结
};
复制代码

1.4モジュール構成定義されました

モジュールのメソッドを確立した後、モジュールは、情報の構造は、モジュールオブジェクトを作成するために必要とされる定義する必要があります。形式は次のとおりです。

{base, name, doc, size, module methods 表}
即 {PyModuleDef_HEAD_INIT, 名字, 描述, 分配内存大小, module 方法列表}
复制代码

関連の定義は、公式ドキュメントを参照することができますdocs.python.org/3/c-api/mod ...

上記の説明によれば、構造関数は、定義されたモジュールです。

// content of speedup_fib.c
static struct PyModuleDef speedup_fib_module = {
    PyModuleDef_HEAD_INIT,
    "speedup_fib",
    "A module containing methods with faster fib.",
    -1, // global state
    SpeedupFibMethods
};
复制代码

1.5定义モジュールの初期化メソッド

次に、モジュールの初期化メソッドを定義し、目的は、構造情報に基づいて、モジュールオブジェクトモジュールを作成することであり、このモジュールの目的は、Pythonのために呼び出すことができます。

モジュールの初期化メソッドはPyInit_を開始する必要があります。

// content of speedup_fib.c
PyMODINIT_FUNC PyInit_speedup_fib() {
  return PyModule_Create(&speedup_fib_module);
}
复制代码

1.6拡張モジュールを確立

上記ステップ5有するspeedup_fib.c完成のコードセクション、作成する必要性setup.pyによって、DistutilsモジュールC言語はモジュールから作成されます。

# content of setup.py
from distutils.core import setup, Extension
speedup_fib_module = Extension('speedup_fib', sources=['speedup_fib.c'])

setup(
    name='SpeedupFib',
    description='A package containing modules for speeding up fib.',
    ext_modules=[speedup_fib_module],
)
复制代码

どの方法C最初に指定して、拡張ファイルを確立するための設定を呼び出しているプログラム。

次のコマンドで:

python3 setup.py build_ext --inplace
复制代码

現在のフォルダに設立しますspeedup_fib.cpython-37m-darwin.so、それは直接Pythonのファイルから呼び出すことができます。

テスト:

from speedup_fib import speedup_fib
start_ts = time.time()
print(speedup_fib(35))
print(time.time() - start_ts)

# 运行结果:
# 9227465
# 0.054654836654663086
复制代码

nが大きい場合、コントラストPythonプログラムの前に、80倍の速さ、速度のギャップはさらに大きくなります。

2.のctypes

あなたはあまりにも面倒な最初の方法を考える場合のctypesを紹介し、その後、ctypesのはlibrayのPythonが提供され、Pythonは関数を呼び出すためのアクセス外部のダイナミックリンクライブラリ(DLL)または共有ライブラリを可能にします。

これは執筆に集中するC、およびCの機能に関連したAPIのPythonに焦点を当てる必要がなくなります。

プログラムの2.1 C言語のバージョン

このステップは、州のいずれかの方法で、すべての上に、プログラムのC言語のバージョンで書かれていないことができます。

// content of speedup_fib.c
long long fib(long long n){
    if(n < 2)
        return n;
    else
        return fib(n-1) + fib(n-2);
};
复制代码

非常に単純ではない、唯一の書き込み機能を集中する必要があり、ヘッダファイルでも必要ありません。

共有ライブラリの2.2設立

このステップでは、gccのツールを使用する必要があり、そうでない場合は、インストールする必要があります。

gcc -shared -fPIC speedup_fib.c -o speedup_fib.so
复制代码

上記のコマンドspeedup_fib.cによってファイルを生成speedup_fib.so。

2.3導入ライブラリ

次に簡単です、ちょうどあなたは、Pythonを実行することができ、speedup_fib.soファイルの導入を改善する方法をctypesは。

# content of fib.py

from ctypes import *
func = cdll.LoadLibrary('./speedup_fib.so')

start_ts = time.time()
print(func.fib(35))
print(time.time() - start_ts)
复制代码

結果を得るfib.py上記のファイルを実行します。

9227465
0.06056809425354004
复制代码

3. SWIG

SWIG(簡体ラッパーとインターフェイスジェネレータ)はPythonやPerl、Ruby、その他の多くの言語をサポートして、より一般的かつ包括的なツールです。

環境が直接マックであればまずあなたは、SWIGをインストールする必要がありますbrew install swigすることができ、公式サイトを参照して、ウィンドウ環境:www.swig.org/Doc3.0/Pref ...

C言語プログラムのバージョン3.1を作成します。

このステップは必要不可欠ですが、コマンドヘッダファイルの.hをSWIGある必要があります。

// content of speedup_fib.h
long long fib(long long n){
    if(n < 2)
        return n;
    else
        return fib(n-1) + fib(n-2);
};
复制代码

3.2インターフェイスファイルを確立

使用次のファイルをインタフェースする、それは言うことができる記述ファイルインタフェースは、* .Iまたは* .swg命名します。

次に、定義します speedup_fib.i

// content of speedup_fib.i

/* 定义 module名称 */
%module speedup_fib

/*导入定义的 speedup_fib.h*/
%{
#include "speedup_fib.h"
%}
/* 告诉 SWIG 定义的 function 或 variable */
long long fib(long long n);
复制代码

上記で定義されspeedup_fib.i、モジュール名を定義する最初のステップは、定義の導入の第二段階speedup_fib.hSWIG内部関数を呼び出し、第3のステップは、関数を宣言することです。

3.3は、ラッパーファイルを生成します

SWIGはspeedup_fib.pyのインタフェースファイルspeedup_fib_wrap.c拡張モジュールとラッパーファイルによって生成されます。

次のようにコマンドは次のとおりです。

swig -python speedup_fib.i
复制代码

speedup_fib.pyとspeedup_fib_wrap.c:現在のフォルダは、二つ以上のファイルになります。

3.4共有ライブラリの構築

パイソン/ Cでのこのステップでは、共有ライブラリの設立で、拡張モジュールのAPIを作成し、setup.pyのDistutilsを使用するには:

# content of setup.py

from distutils.core import setup, Extension

# Extension module name 要有底线前缀
speedup_fib_module = Extension('_speedup_fib', sources=['speedup_fib_wrap.c'])
setup(
    name='SpeedupFib',
    description='A package containing modules for speeding up performance.',
    ext_modules=[speedup_fib_module],
)
复制代码

拡張モジュール名の接頭辞が一番下の行でなければなりません。

そして、次のコマンドを実行します。

python3 setup.py build_ext --inplace
复制代码

現在のフォルダに設立します_speedup_fib.cpython-37m-darwin.so、それは直接Pythonのファイルから呼び出すことができます。

# content of fib.py

from speedup_fib import fib

start_ts = time.time()
print(fib(35))
print(time.time() - start_ts)
复制代码

次のようにfib.py、業績を実行します。

9227465
0.05449485778808594

 

おすすめ

転載: blog.csdn.net/ytp552200ytp/article/details/93467230