[Pythonjp-checkins] [python-doc-ja] push by songo****@gmail***** - Update 2.7.2: extending/extending on 2011-11-10 16:04 GMT

Back to archive index

pytho****@googl***** pytho****@googl*****
2011年 11月 11日 (金) 01:05:56 JST


Revision: 9577393987b4
Author:   Naoki INADA  <inada****@klab*****>
Date:     Thu Nov 10 08:04:53 2011
Log:      Update 2.7.2: extending/extending
http://code.google.com/p/python-doc-ja/source/detail?r=9577393987b4

Modified:
  /extending/extending.rst

=======================================
--- /extending/extending.rst	Wed Aug 24 03:05:50 2011
+++ /extending/extending.rst	Thu Nov 10 08:04:53 2011
@@ -73,9 +73,8 @@
  ここでは、Python の引数リスト (例えば、単一の式 ``"ls -l"``)  から C 関数に 
渡す引数にそのまま変換しています。 C
  関数は常に二つの引数を持ち、便宜的に *self* および *args* と呼ばれます。

-*self* 引数は C 関数が Python の関数ではなく組み込みメソッドを実装している 
場合にのみ使われます。この例ではメソッドではなく
-関数を定義しているので、 *self* は常に *NULL* ポインタになります。 (これ 
は、インタプリタが二つの異なる形式の C 関数を理解しなくてもよく
-するためです。)
+*self* 引数には、モジュールレベルの関数であればモジュールが、メソッドには
+オブジェクトインスタンスが渡されます。

  *args* 引数は、引数の入った Python タプルオブジェクトへのポインタになりま 
す。タプル内の各要素は、呼び出しの際の引数リストに
  おける各引数に対応します。引数は Python オブジェクトです ---  C 関数で引数 
を使って何かを行うには、オブジェクトから C の値に
@@ -323,11 +322,7 @@
     :file:`.so` 、Windows では :file:`.dll`) から読み出された場合にはモジ 
ュールファイルを再読み込みしないので注意してください。

  より実質的なモジュール例は、Python ソース配布物 
に :file:`Modules/xxmodule.c` という名前で入っています。
-このファイルはテンプレートとしても利用できますし、単に例としても読めます。 
ソース配布物や Windows にインストールされた Python に入っている
-:program:`modulator.py` では、拡張モジュールで実装しなければならない
-関数やオブジェクトを宣言し、実装部分を埋めて作成するためのテンプレートを生 
成できるような、簡単なグラフィカルユーザインタフェースを提供しています。
-このスクリプトは :file:`Tools/modulator/` ディレクトリにあります; 詳しくは 
ディレクトリ内の :file:`README`
-ファイルを参照してください。
+このファイルはテンプレートとしても利用できますし、単に例としても読めます。


  .. _compilation:
@@ -915,7 +910,7 @@
  {...}`` が行われるように、ヘッダファイル内にすでに書かれているからです。


-.. _using-cobjects:
+.. _using-capsules:

  拡張モジュールに C API を提供する
  =================================
@@ -940,18 +935,36 @@
  と宣言せねばなりません。例外はモジュールの初期化関数で、これは  
(:ref:`methodtable` で述べたように) 他の拡張モジュールとの間で
  名前が衝突するのを避けるためです。また、他の拡張モジュールからアクセスを  
*受けるべきではない*  シンボルは別のやり方で公開せねばなりません。

-Python はある拡張モジュールの C レベルの情報 (ポインタ) を別のモジュールに 
渡すための特殊な機構: CObject を提供しています。
-CObject はポインタ (:c:type:`void\*`) を記憶する Python のデータ型です。  
CObject は C API
-を介してのみ生成したりアクセスしたりできますが、他の Python オブジェクトと 
同じように受け渡しできます。とりわけ、CObject
-は拡張モジュールの名前空間内にある名前に代入できます。他の拡張モジュールは 
このモジュールを import でき、次に名前を取得し、最後にCObject
+Python はある拡張モジュールの C レベルの情報 (ポインタ) を別のモジュールに 
渡すための
+特殊な機構: Capsule (カプセル)を提供しています。
+Capsule はポインタ (:c:type:`void\*`) を記憶する Python のデータ型です。  
Capsule は C API
+を介してのみ生成したりアクセスしたりできますが、他の Python オブジェクトと 
同じように受け渡しできます。
+とりわけ、Capsule は拡張モジュールの名前空間内にある名前に代入できます。
+他の拡張モジュールはこのモジュールを import でき、次に名前を取得し、最後に 
Capsule
  へのポインタを取得します。

-拡張モジュールの C API を公開するために、様々な方法で CObject が使われま 
す。エクスポートされているそれぞれの名前を使うと、CObject
-自体や、CObject が公表しているアドレスで示される配列内に収められた全ての C  
API ポインタを得られます。
-そして、ポインタに対する保存や取得といった様々な作業は、コードを提供してい 
るモジュールとクライアントモジュールとの間では異なる方法で分散できます。
+拡張モジュールの C API を公開するために、様々な方法で Capsule が使われま 
す。
+各関数を1つのオブジェクトに入れたり、全ての C API のポインタ配列を Capsule  
に入れることができます。
+そして、ポインタに対する保存や取得といった様々な作業は、コードを提供してい 
る
+モジュールとクライアントモジュールとの間では異なる方法で分散できます。
+
+どの方法を選ぶにしても、 Capsule の name を正しく設定することは重要です。
+:c:func:`PyCapsule_New` は name 引数 (:c:type:`const char \*`) を取ります。
+*NULL* を name に渡すことも許可されていますが、 name を設定することを強く推 
奨します。
+正しく名前を付けられた Capsule はある程度の実行時型安全性を持ちます。
+名前を付けられていない Capsule を他の Capsule と区別する現実的な方法はあり 
ません。
+
+特に、 C API を公開するための Capsule には次のルールに従った名前を付けるべ 
きです::
+
+    modulename.attributename
+
+:c:func:`PyCapsule_Import` という便利関数は、 Capsule の名前がこのルールに 
一致しているときにのみ、
+簡単に Capsule 経由で公開されている C API をロードすることができます。
+この挙動により、 C API のユーザーが、確実に正しい C API を格納している  
Capsule を
+ロードできたことを確かめることができます。

  以下の例では、名前を公開するモジュールの作者にほとんどの負荷が掛かります 
が、よく使われるライブラリを作る際に適切なアプローチを実演します。
-このアプローチでは、全ての C API ポインタ (例中では一つだけですが!) を、  
CObject の値となる :c:type:`void`
+このアプローチでは、全ての C API ポインタ (例中では一つだけですが!) を、  
Capsule の値となる :c:type:`void`
  ポインタの配列に保存します。拡張モジュールに対応するヘッダファイルは、モジ 
ュールの import  と C API
  ポインタを取得するよう手配するマクロを提供します; クライアントモジュール 
は、C API にアクセスする前にこのマクロを呼ぶだけです。

@@ -1011,8 +1024,8 @@
         /* C API ポインタ配列を初期化する */
         PySpam_API[PySpam_System_NUM] = (void *)PySpam_System;

-       /* API ポインタ配列のアドレスが入った CObject を生成する */
-       c_api_object = PyCObject_FromVoidPtr((void *)PySpam_API, NULL);
+       /* API ポインタ配列のアドレスが入った Capsule を生成する */
+       c_api_object = PyCapsule_New((void *)PySpam_API, "spam._C_API",  
NULL);

         if (c_api_object != NULL)
             PyModule_AddObject(m, "_C_API", c_api_object);
@@ -1053,28 +1066,14 @@
     #define PySpam_System \
      (*(PySpam_System_RETURN (*)PySpam_System_PROTO)  
PySpam_API[PySpam_System_NUM])

-   /* エラーによる例外の場合には -1 を、成功すると 0 を返す */
+   /* エラーによる例外の場合には -1 を、成功すると 0 を返す
+    * エラーがあれば PyCapsule_Import が例外を設定する。
+    */
     static int
     import_spam(void)
     {
-       PyObject *c_api_object;
-       PyObject *module;
-
-       module = PyImport_ImportModule("spam");
-       if (module == NULL)
-           return -1;
-
-       c_api_object = PyObject_GetAttrString(module, "_C_API");
-       if (c_api_object == NULL) {
-           Py_DECREF(module);
-           return -1;
-       }
-       if (PyCObject_Check(c_api_object))
-           PySpam_API = (void **)PyCObject_AsVoidPtr(c_api_object);
-
-       Py_DECREF(c_api_object);
-       Py_DECREF(module);
-       return 0;
+       PySpam_API = (void **)PyCapsule_Import("spam._C_API", 0);
+       return (PySpam_API != NULL) ? 0 : -1;
     }

     #endif
@@ -1104,10 +1103,10 @@
  このアプローチの主要な欠点は、 :file:`spammodule.h` がやや難解になるという 
ことです。とはいえ、各関数の基本的な構成は公開される
  ものと同じなので、書き方を一度だけ学べばすみます。

-最後に、CObject は、自身に保存されているポインタをメモリ確保したり解放した 
りする際に特に便利な、もう一つの機能を提供しているという
+最後に、Capsule は、自身に保存されているポインタをメモリ確保したり解放した 
りする際に特に便利な、もう一つの機能を提供しているという
  ことに触れておかねばなりません。詳細は Python/C API リファレンスマニュアル 
の
-:ref:`cobjects` 、および CObjects の実装部分 (Python
-ソースコード配布物中のファイル  :file:`Include/cobject.h` およ 
び :file:`Objects/cobject.c`
+:ref:`capsules`, および Capsule の実装部分 (Python
+ソースコード配布物中のファイル  :file:`Include/pycapsule.h` およ 
び :file:`Objects/pycapsule.c`
  に述べられています。

  .. rubric:: 脚注




Pythonjp-checkins メーリングリストの案内
Back to archive index