diff options
author | mattip <matti.picus@gmail.com> | 2018-09-25 13:19:41 +0300 |
---|---|---|
committer | mattip <matti.picus@gmail.com> | 2018-09-25 14:43:41 +0300 |
commit | 4a8e481a419d034e1ad47d2a3c9fb244e91d19a0 (patch) | |
tree | e930352f5671dd578103eafb3e0c512711a23b25 /docs | |
parent | 9f2869067b2cf8e86aa0c52fad90a477fe7fae87 (diff) | |
download | cython-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.rst | 66 | ||||
-rw-r--r-- | docs/src/userguide/external_C_code.rst | 1 |
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``. |