summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authormattip <matti.picus@gmail.com>2018-09-25 13:19:41 +0300
committermattip <matti.picus@gmail.com>2018-09-25 14:43:41 +0300
commit4a8e481a419d034e1ad47d2a3c9fb244e91d19a0 (patch)
treee930352f5671dd578103eafb3e0c512711a23b25 /docs
parent9f2869067b2cf8e86aa0c52fad90a477fe7fae87 (diff)
downloadcython-4a8e481a419d034e1ad47d2a3c9fb244e91d19a0.tar.gz
DOC, TST: test and document external extension type attribute aliasing
Diffstat (limited to 'docs')
-rw-r--r--docs/src/userguide/extension_types.rst66
-rw-r--r--docs/src/userguide/external_C_code.rst1
2 files changed, 67 insertions, 0 deletions
diff --git a/docs/src/userguide/extension_types.rst b/docs/src/userguide/extension_types.rst
index 0f0282ea2..340fac6fc 100644
--- a/docs/src/userguide/extension_types.rst
+++ b/docs/src/userguide/extension_types.rst
@@ -771,6 +771,72 @@ For public extension types, the object and type clauses are both required,
because Cython must be able to generate code that is compatible with external C
code.
+Attribute name matching and aliasing
+------------------------------------
+
+Sometimes the type's C struct as specified in ``object_struct_name`` may use
+different labels for the fields. For example we may have an extension module
+``foo_extension``::
+
+ cdef class Foo:
+ cdef public int field0, field1, field2;
+
+ def __init__(self, f0, f1, f2):
+ self.field0 = f0
+ self.field1 = f1
+ self.field2 = f2
+
+but a C struct in a file ``foo_nominal.h``::
+
+ typedef struct {
+ PyObject_HEAD
+ int f0;
+ int f1;
+ int f2;
+ } FooStructNominal;
+
+Note that the struct uses ``f0``, ``f1``, ``f2`` but they are ``field0``,
+``field1``, and ``field2`` in ``Foo``. We are given this situation, including
+a header file with that struct, and we wish to write a function to sum the
+values. If we write an extension module ``wrapper``::
+
+ cdef extern from "foo_nominal.h":
+
+ ctypedef class foo_extension.Foo [object FooStructNominal]:
+ cdef:
+ int field0
+ int field1
+ int feild2
+
+ def sum(Foo f):
+ return f.field0 + f.field1 + f.field2
+
+then ``wrapper.sum(f)`` (where ``f = foo_extension.Foo(1, 2, 3)``) will still
+use the C-API equivalent of::
+
+ return f.__getattr__('field0') +
+ f.__getattr__('field1') +
+ f.__getattr__('field1')
+
+instead of the desired C equivalent of ``return f->f0 + f->f1 + f->f2``. We can
+alias the fields by using::
+ cdef extern from "foo_nominal.h":
+
+ ctypedef class foo_extension.Foo [object FooStructNominal]:
+ cdef:
+ int field0 "f0"
+ int field1 "f1"
+ int field2 "f2"
+
+ def sum(Foo f) except -1:
+ return f.field0 + f.field1 + f.field2
+
+and now Cython will replace the slow ``__getattr__`` with direct C access to
+the FooStructNominal fields. This is useful when directly processing Python
+code. No changes to Python need be made to achieve significant speedups, even
+though the field names in Python and C are different. Of course, one should
+make sure the fields are equivalent.
+
Implicit importing
------------------
diff --git a/docs/src/userguide/external_C_code.rst b/docs/src/userguide/external_C_code.rst
index d8d6eb867..80764b253 100644
--- a/docs/src/userguide/external_C_code.rst
+++ b/docs/src/userguide/external_C_code.rst
@@ -219,6 +219,7 @@ same applies equally to union and enum declarations.
| } Foo; | | |
+-------------------------+---------------------------------------------+-----------------------------------------------------------------------+
+See also use of :ref:`external_extension_types`.
Note that in all the cases below, you refer to the type in Cython code simply
as :c:type:`Foo`, not ``struct Foo``.