名前にかかわらずコメントが正しく促されたため、この記事ではコードの直接埋め込みではなく、Pythonでの共有ライブラリの作成に焦点を当てます。 しかし、これは単なる翻訳なので、名前を元の名前に近づけることにしました。
PyGrunn 2016カンファレンスで、Python cffiパッケージと、CアプリケーションにPyPyコードを埋め込むためのその使用についてプレゼンテーションを行いました。
cffi 1.5.0のリリースとその後のPyPy 5への組み込みにより、PyPyコードを埋め込むことが可能になりました。 これを行うには、Pythonコードを動的ライブラリにコンパイルします。動的ライブラリは、他の言語で使用できます。 この記事では、その方法を紹介します。
組み込みAPI
最初のステップは、CアプリケーションがPythonコードを呼び出す方法を定義するインターフェースを定義することです。 C関数のプロトタイプを使用してこれを示す必要があります。 この例では、ある種の計算を実行する関数を考えますが、もちろんそれは何でもかまいません。
float compute(float first, float second);
次に、これらの計算をPythonで実装する必要があります。
from my_library import ffi, lib @ffi.def_extern() def compute(first, second): """ . """ return abs(first - second)
このスニペットには、正しく埋め込むためのいくつかの特別なものが含まれています。 最初の行は、ダイナミックライブラリから
ffi
および
lib
オブジェクトをインポートします。 これを行うことにより、実装はcffiによって提供される関数にアクセスし、メモリの割り当てなどのより複雑なタスクに使用できます。 名前
my_library
以下で定義され、動的ライブラリの名前と一致します。
このフラグメントで2番目に気づくのは、
@ffi.def_extern
デコレータです。 彼は、装飾された関数がCライブラリによって作成されたパブリックAPIで表されるべきであるとcffiに伝えます。 装飾された関数は、API宣言およびその引数で指定されたプロトタイプと比較され、戻り値は自動的に変換されます。
ライブラリ生成スクリプト
APIとその実装ができたので、実際にどこかに埋め込む必要があります。 これを行うには、動的ライブラリを生成するスクリプトを使用します。 上記の2つのコードスニペットが
api.h
および
implementation.py
ファイルに含まれている
api.h
あります。
import cffi ffi = cffi.FFI() ffi.embedding_api(open("api.h").read()) ffi.embedding_init_code(open("implementation.py").read()) ffi.set_source("my_library", "") ffi.compile(verbose=True)
このスクリプトは非常に簡単です。 APIを指定し、その実装を提供する必要があります。 これらは両方ともディスクから読み取られ、前のセクションで指定されたコードフラグメントに対応します。
ソースを指定したら、ライブラリの名前をcffiに伝える必要があります。 この例では、これは
my_library
です。 さらに、対応するヘッダーファイルを接続するなどして、APIのヘッダーファイルに型を提供するCコードを追加する場所があります(これは
embedding_api
許可されていません)。 ライブラリのファイルを作成するためにソースをコンパイルするだけです。
スクリプトを実行すると、いくつかの情報が表示され、ライブラリが作成されます。
$ pypy embed.py generating ./my_library.c running build_ext building 'my_library' extension ... $ ls my_library.dylib -rwxr-xr-x 1 djinn staff 9856 May 15 14:46 my_library.dylib
あとは、どこかで使用するだけです!
アプリケーションを使用する
埋め込みPythonコードの使用は実際には非常に簡単です。 これは、次のコードを使用して実行できます。
#include <stdio.h> #include "api.h" int main(void) { float result = compute(12.34f, 10.0f); printf("The result: %f\n", result); return 0; }
ご覧のとおり、Pythonコードを呼び出すのにほとんど何も必要ありません。 CPython APIを使用すると、インタープリターを起動し、多くのパラメーターと戻り値の変換を実行する必要があります。 しかし、cffiではありません! 作成されたライブラリがすべてを処理するため、本当に便利な作業に集中できます。 最後に示す必要があるのは、このコードをコンパイルして実行する方法です。
$ clang -o test test.c my_library.dylib $ ./test The result: 2.340000
そしてここにある! ほんの数行のコードで、PyPyインタープリターを実行し、PythonコードをあたかもCコードであるかのように実行するCプログラムを作成しました。もちろん、基本だけを示しましたが、それは本当に強力なテクノロジーです。 詳細については、 cffiのドキュメントを参照してください。