summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgabrieldemarmiesse <gabriel.demarmiesse@teraki.com>2018-06-13 15:43:12 +0200
committergabrieldemarmiesse <gabriel.demarmiesse@teraki.com>2018-06-13 15:43:12 +0200
commit8e3a8af1a6ddcb4c9b42df962fdc6fb14b0671ea (patch)
tree89aec458a2647162ad1acc7ccb221cdc0b96499e
parent5fadf79efd37273873c1be2353969445118ed903 (diff)
downloadcython-8e3a8af1a6ddcb4c9b42df962fdc6fb14b0671ea.tar.gz
Added tests for some of the code snippets in "calling C libraries". Fixed a forgotten import.
-rw-r--r--docs/examples/tutorial/clibraries/c-algorithms/src/queue.h17
-rw-r--r--docs/examples/tutorial/clibraries/cqueue.pxd19
-rw-r--r--docs/examples/tutorial/clibraries/queue.pyx9
-rw-r--r--docs/examples/tutorial/clibraries/queue2.pyx11
-rw-r--r--docs/examples/tutorial/clibraries/test_queue.py36
-rw-r--r--docs/src/tutorial/clibraries.rst104
6 files changed, 103 insertions, 93 deletions
diff --git a/docs/examples/tutorial/clibraries/c-algorithms/src/queue.h b/docs/examples/tutorial/clibraries/c-algorithms/src/queue.h
new file mode 100644
index 000000000..642bf54af
--- /dev/null
+++ b/docs/examples/tutorial/clibraries/c-algorithms/src/queue.h
@@ -0,0 +1,17 @@
+/* queue.h */
+
+typedef struct _Queue Queue;
+typedef void *QueueValue;
+
+Queue *queue_new(void);
+void queue_free(Queue *queue);
+
+int queue_push_head(Queue *queue, QueueValue data);
+QueueValue queue_pop_head(Queue *queue);
+QueueValue queue_peek_head(Queue *queue);
+
+int queue_push_tail(Queue *queue, QueueValue data);
+QueueValue queue_pop_tail(Queue *queue);
+QueueValue queue_peek_tail(Queue *queue);
+
+int queue_is_empty(Queue *queue);
diff --git a/docs/examples/tutorial/clibraries/cqueue.pxd b/docs/examples/tutorial/clibraries/cqueue.pxd
new file mode 100644
index 000000000..13a07d317
--- /dev/null
+++ b/docs/examples/tutorial/clibraries/cqueue.pxd
@@ -0,0 +1,19 @@
+# cqueue.pxd
+
+cdef extern from "c-algorithms/src/queue.h":
+ ctypedef struct Queue:
+ pass
+ ctypedef void* QueueValue
+
+ Queue* queue_new()
+ void queue_free(Queue* queue)
+
+ int queue_push_head(Queue* queue, QueueValue data)
+ QueueValue queue_pop_head(Queue* queue)
+ QueueValue queue_peek_head(Queue* queue)
+
+ int queue_push_tail(Queue* queue, QueueValue data)
+ QueueValue queue_pop_tail(Queue* queue)
+ QueueValue queue_peek_tail(Queue* queue)
+
+ bint queue_is_empty(Queue* queue)
diff --git a/docs/examples/tutorial/clibraries/queue.pyx b/docs/examples/tutorial/clibraries/queue.pyx
new file mode 100644
index 000000000..5363ee4f5
--- /dev/null
+++ b/docs/examples/tutorial/clibraries/queue.pyx
@@ -0,0 +1,9 @@
+# queue.pyx
+
+cimport cqueue
+
+cdef class Queue:
+ cdef cqueue.Queue* _c_queue
+
+ def __cinit__(self):
+ self._c_queue = cqueue.queue_new()
diff --git a/docs/examples/tutorial/clibraries/queue2.pyx b/docs/examples/tutorial/clibraries/queue2.pyx
new file mode 100644
index 000000000..9278fbf4b
--- /dev/null
+++ b/docs/examples/tutorial/clibraries/queue2.pyx
@@ -0,0 +1,11 @@
+# queue.pyx
+
+cimport cqueue
+
+cdef class Queue:
+ cdef cqueue.Queue* _c_queue
+
+ def __cinit__(self):
+ self._c_queue = cqueue.queue_new()
+ if self._c_queue is NULL:
+ raise MemoryError()
diff --git a/docs/examples/tutorial/clibraries/test_queue.py b/docs/examples/tutorial/clibraries/test_queue.py
new file mode 100644
index 000000000..5390a82c1
--- /dev/null
+++ b/docs/examples/tutorial/clibraries/test_queue.py
@@ -0,0 +1,36 @@
+from __future__ import print_function
+
+import time
+
+import queue
+
+Q = queue.Queue()
+
+Q.append(10)
+Q.append(20)
+print(Q.peek())
+print(Q.pop())
+print(Q.pop())
+try:
+ print(Q.pop())
+except IndexError as e:
+ print("Error message:", e) # Prints "Queue is empty"
+
+i = 10000
+
+values = range(i)
+
+start_time = time.time()
+
+Q.extend(values)
+
+end_time = time.time() - start_time
+
+print("Adding {} items took {:1.3f} msecs.".format(i, 1000 * end_time))
+
+for i in range(41):
+ Q.pop()
+
+Q.pop()
+print("The answer is:")
+print(Q.pop())
diff --git a/docs/src/tutorial/clibraries.rst b/docs/src/tutorial/clibraries.rst
index 34c4d9bfb..9b779370d 100644
--- a/docs/src/tutorial/clibraries.rst
+++ b/docs/src/tutorial/clibraries.rst
@@ -33,48 +33,15 @@ Defining external declarations
You can download CAlg `here <https://github.com/fragglet/c-algorithms/archive/master.zip>`_.
The C API of the queue implementation, which is defined in the header
-file ``c-algorithms/src/queue.h``, essentially looks like this::
+file ``c-algorithms/src/queue.h``, essentially looks like this:
- /* file: queue.h */
-
- typedef struct _Queue Queue;
- typedef void *QueueValue;
-
- Queue *queue_new(void);
- void queue_free(Queue *queue);
-
- int queue_push_head(Queue *queue, QueueValue data);
- QueueValue queue_pop_head(Queue *queue);
- QueueValue queue_peek_head(Queue *queue);
-
- int queue_push_tail(Queue *queue, QueueValue data);
- QueueValue queue_pop_tail(Queue *queue);
- QueueValue queue_peek_tail(Queue *queue);
-
- int queue_is_empty(Queue *queue);
+.. literalinclude:: ../../examples/tutorial/clibraries/c-algorithms/src/queue.h
+ :language: C
To get started, the first step is to redefine the C API in a ``.pxd``
-file, say, ``cqueue.pxd``::
-
- # file: cqueue.pxd
-
- cdef extern from "c-algorithms/src/queue.h":
- ctypedef struct Queue:
- pass
- ctypedef void* QueueValue
-
- Queue* queue_new()
- void queue_free(Queue* queue)
-
- int queue_push_head(Queue* queue, QueueValue data)
- QueueValue queue_pop_head(Queue* queue)
- QueueValue queue_peek_head(Queue* queue)
-
- int queue_push_tail(Queue* queue, QueueValue data)
- QueueValue queue_pop_tail(Queue* queue)
- QueueValue queue_peek_tail(Queue* queue)
+file, say, ``cqueue.pxd``:
- bint queue_is_empty(Queue* queue)
+.. literalinclude:: ../../examples/tutorial/clibraries/cqueue.pxd
Note how these declarations are almost identical to the header file
declarations, so you can often just copy them over. However, you do
@@ -144,16 +111,9 @@ class that should wrap the C queue. It will live in a file called
library, there must not be a ``.pyx`` file with the same name
that Cython associates with it.
-Here is a first start for the Queue class::
+Here is a first start for the Queue class:
- # file: queue.pyx
-
- cimport cqueue
-
- cdef class Queue:
- cdef cqueue.Queue* _c_queue
- def __cinit__(self):
- self._c_queue = cqueue.queue_new()
+.. literalinclude:: ../../examples/tutorial/clibraries/queue.pyx
Note that it says ``__cinit__`` rather than ``__init__``. While
``__init__`` is available as well, it is not guaranteed to be run (for
@@ -190,16 +150,9 @@ that case, it will return ``NULL``, whereas it would normally return a
pointer to the new queue.
The Python way to get out of this is to raise a ``MemoryError`` [#]_.
-We can thus change the init function as follows::
-
- cimport cqueue
+We can thus change the init function as follows:
- cdef class Queue:
- cdef cqueue.Queue* _c_queue
- def __cinit__(self):
- self._c_queue = cqueue.queue_new()
- if self._c_queue is NULL:
- raise MemoryError()
+.. literalinclude:: ../../examples/tutorial/clibraries/queue2.pyx
.. [#] In the specific case of a ``MemoryError``, creating a new
exception instance in order to raise it may actually fail because
@@ -587,44 +540,9 @@ instead that accepts an arbitrary Python iterable::
Now we can test our Queue implementation using a python script,
-for example here :file:`test_queue.py`.::
-
- from __future__ import print_function
-
- import queue
-
-
- Q = queue.Queue()
-
- Q.append(10)
- Q.append(20)
- print(Q.peek())
- print(Q.pop())
- print(Q.pop())
- try:
- print(Q.pop())
- except IndexError as e:
- print("Error message:", e) # Prints "Queue is empty"
-
- i = 10000
-
- values = range(i)
-
- start_time = time.time()
-
- Q.extend(values)
-
- end_time = time.time() - start_time
-
- print("Adding {} items took {:1.3f} msecs.".format(i, 1000 * end_time))
-
- for i in range(41):
- Q.pop()
-
- Q.pop()
- print("The answer is:")
- print(Q.pop())
+for example here :file:`test_queue.py`:
+.. literalinclude:: ../../examples/tutorial/clibraries/test_queue.py
As a quick test with 10000 numbers on the author's machine indicates,
using this Queue from Cython code with C ``int`` values is about five