Commits

Anonymous committed 4ec5baf

source/simobj.rst を追加 (英語バージョンより翻訳+α)

  • Participants
  • Parent commits f70e640

Comments (0)

Files changed (3)

    :maxdepth: 2
 
    tutorial
+   simobj
    utils
 
 - リポジトリ: http://bitbucket.org/tkf/railgun/

source/simobj.rst

+:class:`SimObject`: Cの共有ライブラリから必要な関数をロードしてくれるクラス
+===========================================================================
+
+.. module:: railgun
+
+
+.. class:: SimObject
+
+   このクラスをオーバーロードした子クラスを作ることで,自動的にCの関数を
+   Pythonから呼び出せるようになります.その子クラスの名前は,対応する
+   Cの構造体の名前と同じである必要があります.別の名前を使う方法については,
+   :attr:`_cstructname_` や :attr:`_cfuncprefix_` を参照してください.
+
+   RailGun は特別な属性(attribute)を使うので,それを定義している必要が
+   あります.特に, :attr:`_clibname_`, :attr:`_clibdir_`,
+   :attr:`_cmembers_` and :attr:`_cfuncs_` は最低限必要な属性です.
+
+   Example::
+
+       class NameOfCStruct(SimObject):
+           _clibname_ = 'name_of_shared_library.so'
+           _clibdir_ = 'path/to/shared/library'
+
+           _cmembers_ = [
+               'num_i',
+               'num_j',
+               'int scalar',
+               'int vector[i]',
+               'int matrix[i][j]',
+               ...
+               ]
+
+           _cfuncs_ = [
+               'name_of_c_function',
+               ...
+               ]
+
+           def __init__(self, num_i, num_j, **kwds):
+               SimObject.__init__(self, num_i=num_i, num_j=num_j, **kwds)
+
+           def some_function(self, ...):
+               ...
+
+   - :meth:`__init__` はオーバーライド可能です.
+   - Cの関数(:attr:`_cfuncs_`)や構造体メンバー(:attr:`_cmembers_`)と
+     名前が被らない限り,Pythonの関数を定義したり,メンバー変数を
+     用いても問題ありません.
+   - Cの関数や構造体メンバーと名前が被ると,上書きされてしまいます.
+
+
+   .. attribute:: SimObject._clibname_
+
+      共有ライブラリのファイル名です.
+
+   .. attribute:: SimObject._clibdir_
+
+      共有ライブラリのあるディレクトリへのパスです.
+      :func:`relpath` を使って指定するのが便利です.
+
+   .. attribute:: SimObject._cmembers_
+
+      C構造体のメンバー変数の定義のリストです.
+      このリストの各要素は文字列で,それぞれの文字列がメンバー変数の定義に
+      対応します.
+      メンバー変数は次のような形式で定義されます.::
+
+           [CDT] VAR_NAME[INDEX] [= DEFAULT]
+
+      **VAR_NAME**: メンバー変数の名前
+          Python側から, `obj.VAR_NAME` のようにこのメンバ変数に
+          アクセスできるようになります.
+
+          この名前が ``num_`` から始まるとその後に続く文字列は
+          配列の添字だと見なされます.例えば, ``num_i`` は添字 ``i``
+          を定義し, ``num_i`` の値は添字 ``i`` に沿った配列の長さです.
+          ``num_`` から始まる **VAR_NAME** は,次の **CDT** を省略
+          できます.
+      **CDT**: C Data Type, (変数が ``num_`` から始まる場合は省略可)
+          整数 (`int`) や浮動小数点 (`double`) などのCの型を定義します.
+          `C Data Type (CDT) と numpy の dtype と ctypes の対応関係`_
+          から選んでください.
+      **INDEX**: index, optional
+          変数が配列の場合はこの **INDEX** を指定してください.
+          配列が ``num_i1`` x ``num_i2`` x ... x ``num_iN``
+          という形をしているなら, **INDEX** は ``[i1][i2]...[iN]``
+          となります.
+      **DEFAULT**: a number, optional
+          この変数のデフォルトの値です.この変数が配列の場合は,
+          すべての要素がこの値で埋め尽くされます.
+
+      .. warning::
+
+         この定義はCの構造体と同じ順序でなければいけません!
+
+      例::
+
+          _cmembers_ = [
+              'num_i', 'num_j', 'num_k',
+              'int int_scalar',
+              'int int_vector1[i]',
+              'int int_vector2[j] = 0',
+              'int int_matrix[i][j]',
+              'double double_scalar = 0.1',
+              'double double_vector[k] = 18.2',
+              'double double_matrix[k][i] = -4.1',
+              ]
+
+      参照: :func:`cm.int`
+
+   .. attribute:: SimObject._cfuncs_
+
+      Cの関数の定義のリストです.
+      このリストの各要素は文字列で,それぞれの文字列が関数の定義に
+      対応します.
+      Cの関数は次のような形式で定義されます.::
+
+          [RETURN_VAR] FUNC_NAME([ARG, ARG, ...])
+
+      **FUNC_NAME**: string
+          Cの関数の名前です.構造体の名前は含める必要はありません.
+
+          参照: :ref:`choices`.
+      **RETURN_VAR**: string, optional
+          Cの構造体のメンバの名前です.
+          もしこの名前が定義されていれば,このC関数に対応するPythonの関数
+          は, **RETURN_VAR** の値を返すようになります。
+      **ARG**:
+          C関数の引数です.以下の形式で定義されます.::
+
+              CDT_OR_INDEX ARG_NAME [= DEFAULT]
+
+          **CDT_OR_INDEX**: string
+              C Data Type (CDT) または 添字.
+              添字 ``i`` (``i<``) が指定された場合,引数 `x` が
+              ``0 <= x < num_i`` (``0 < x <= num_i``) を満足しない場合
+              にはエラーを発生します.
+          **ARG_NAME**: string
+              引数の名前です.Python側で, `FUNC_NAME(ARG_NAME=value)`
+              のような呼び出しが出来ます.
+          **DEFAULT**: a number or member of C struct, optional
+              この引数のデフォルトの値です.
+
+          C関数の第一引数であるCの構造体のポインタ (``*self``) は
+          この引数の定義には含めないで下さい.
+
+      例::
+
+          _cfuncs_ = [
+              "func_spam()",
+              "bar func_foo()",
+              "func_with_args(int a, double b, i start=0, i< end=num_i)",
+              "func_{key | c1, c2, c3}()",
+              ]
+
+      参照: :ref:`how_to_write_cfunc`
+
+   .. attribute:: SimObject._cstructname_
+
+      この属性の指定は任意です.
+      Cの構造体の名前を明示的に与えることが出来ます.
+      もしこの :attr:`_cstructname_` 属性が指定されない場合は,
+      自動的にクラス名をCの構造体の名前として使います.::
+
+           class CStructName(SimObject):  # 'CStructName' is name of c-struct
+               ...
+
+           class OtherNameForPyClass(SimObject):
+               ...
+               _cstructname_ = 'CStructName'  # this is name of c-struct
+
+
+   .. attribute:: SimObject._cfuncprefix_
+
+      この属性の指定は任意です.
+      Cの関数のプレフィックスを指定するのに使います.
+      デフォルトは,「 "Cの構造体名" + ``_`` 」です.::
+
+           class YourSimObj(SimObject):
+               ...
+               _cfuncprefix_ = 'MyPrefix'
+               _cfuncs_ = [
+                   "FuncName()",  # 'MyPrefixFuncName' will be loaded
+                   ...
+                   ]
+
+           class YourSimObj(SimObject):
+               ...
+               _cfuncprefix_ = ''
+               _cfuncs_ = [
+                   "FuncName()",  # 'FuncName' will be loaded
+                   ...
+                   ]
+
+   .. attribute:: SimObject._cmemsubsets_
+
+      この属性の指定は任意です.
+      この属性を指定することでCメンバーと関数のサブセットに名前をつけ,
+      どのCメンバーのメモリを確保するかを指定することができるようになります.
+      以下のように,辞書の辞書のリストという形式で指定してください.::
+
+          { 'name1': { 'cfuncs': ['f', 'g', 'h'], 'cmems': ['x', 'y'] },
+            'name2': { 'cfuncs': ['f', 'j', 'k'], 'cmems': ['y', 'z'] } }
+
+      ここで, ``name1, name2`` はCメンバーのサブセットの名前で,
+      ``f, g, h, j, k`` はCの関数の名前で,
+      ``x, y, z`` はCの構造体メンバーの名前です.
+      この定義は,
+
+          - 関数 ``f, g, h`` は メンバー変数 ``x, y`` を使う
+          - 関数 ``f, j, k`` は メンバー変数 ``y, z`` を使う
+
+      ということを表しています.
+
+      :meth:`__init__` を呼び出す時に `_cmemsubsets_name1=True` という
+      パラメータを与えて以下のように呼び出すことで ``name1`` のサブセットの
+      メモリーを確保することが出来ます.::
+
+          NameOfCStruct(..., _cmemsubsets_name1=True)
+
+      この時, ``NameOfCStruct.g`` と ``NameOfCStruct.h`` が使えるように
+      なりますが, ``NameOfCStruct.f`` は使えません.なぜなら, ``f`` は
+      ``name2`` のサブセットにも含まれているからです.
+
+      この :attr:`_cmemsubsets_` 属性を使うことで,デバッグ用の
+      メンバー変数や関数などを自然に定義することが出来ます.
+
+   .. method:: SimObject._cwrap_C_FUNC_NAME(func)
+
+      この属性の指定は任意です.
+      ``C_FUNC_NAME`` という名前のC関数の呼び出しをラップするために
+      使うラッパー用関数です.デコレータのような形式で定義します.
+
+      例::
+
+          class YourSimObj(SimObject):
+
+              _clibname_ = '...'
+              _clibdir_ = '...'
+              _cmembers_ = [
+                  'num_i',
+                  'int vec[i]',
+                  ]
+              _cfuncs_ = [
+                  'your_c_function',
+                  ]
+
+              def _cwrap_your_c_function(old_c_function):
+                  def your_c_function(self, *args, **kwds):
+                      old_c_function(self, *args, **kwds)
+                      return self.vec[:]  # return copy
+                  return your_c_function
+
+      C関数 `your_c_function` が読み込まれた後,このラッパー用の関数は
+      次のように呼び出され,新しいPythonのメソッド `your_c_function` が
+      定義されます.::
+
+          your_c_function = _cwrap_your_c_function(your_c_function)
+
+
+   .. method:: SimObject.setv(**kwds)
+
+      この関数は,Cの構造体メンバーの値を変更するのに使います.
+
+      以下の2つの呼び出しは等価です.::
+
+           obj.setv(scalar=1, array=[1, 2, 3])
+           obj.scalar = 1; obj.array = [1, 2, 3]
+
+      配列の要素は, ``var_0_1`` のようなエイリアスが定義されています.
+      以下の2つの呼び出しは等価です.::
+
+           obj.setv(var_0_1=1)
+           obj.var[0][1] = 1
+
+
+   .. method:: SimObject.getv(*args)
+
+      Cメンバーの値を取り出すための関数です.
+      以下の2つの呼び出しは等価です.::
+
+           var = obj.var
+           var = obj.getv('var')
+
+      このメソッドは,いくつものメンバーの値を取り出したい時に便利です.
+      以下の3つの呼び出しは等価です.::
+
+           (a, b, c) = (obj.a, obj.b, obj.c)
+           (a, b, c) = obj.getv('a', 'b', 'c')
+           (a, c, c) = obj.getv('a, b, c')
+
+
+   .. method:: SimObject.num(*args)
+
+      添字にそった配列の長さを返します.
+      以下の2つの呼び出しは等価です.::
+
+           num_i = obj.num_i
+           num_i = obj.num('i')
+
+      複数の添字を指定することも出来ます.
+      以下の3つの呼び出しは等価です.::
+
+           (num_i, num_j, num_k) = (obj.num_i, obj.num_j, obj.num_k)
+           (num_i, num_j, num_k) = obj.num('i', 'j', 'k')
+           (num_i, num_j, num_k) = obj.num('i, j, k')
+
+
+C Data Type (CDT) と numpy の dtype と ctypes の対応関係
+--------------------------------------------------------
+
+以下の C Data Types (**CDTs**) を使って,C構造体のメンバーを指定することが
+出来ます.
+
+================ ============================== ============= ================
+ CDT              C-language type                numpy dtype   ctypes
+================ ============================== ============= ================
+``char``          :c:type:`char`                 `character`   `c_char`
+``short``         :c:type:`short`                `short`       `c_short`
+``ushort``        :c:type:`unsigned short`       `ushort`      `c_ushort`
+``int``           :c:type:`int`                  `int32`       `c_int`
+``uint``          :c:type:`unsigned int`         `uint32`      `c_uint`
+``long``          :c:type:`long`                 `int32` or    `c_long`
+                                                 `int64`
+``ulong``         :c:type:`unsigned long`        `uint32` or   `c_ulong`
+                                                 `uint64`
+``longlong``      :c:type:`long long`            `longlong`    `c_longlong`
+``ulonglong``     :c:type:`unsigned long long`   `ulonglong`   `c_ulonglong`
+``float``         :c:type:`float`                `float32`     `c_float`
+``double``        :c:type:`double`               `float`       `c_double`
+``longdouble``    :c:type:`long double`          `longdouble`  `c_longdouble`
+``bool``          :c:type:`bool`                 `bool`        `c_bool`
+================ ============================== ============= ================
+
+.. note::
+
+   **CDT** `long` / `ulong` に対応する numpy の dtype は
+   :func:`platform.architecture` を使ったプラットフォームの判定に従って
+   決定しています.

source/tutorial.rst

 から変数を読み書きしたい場合はすべて構造体の中に入れてください.
 
 
+.. _how_to_write_cfunc:
+
 Python から呼び出す関数
 ^^^^^^^^^^^^^^^^^^^^^^^
 
       のように,整数,浮動小数点,もしくは構造体メンバから指定
       することが出来ます.
 
+.. _choices:
 
 複数のC関数を一気に読み込む ``{key|c1,c2}``-記法 (*choices*)
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^