Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2a1e74a

Browse files
committed
Issue #13709: some fixes to the ctypes documentation. In addition to fixing
the problems pointed in the issue, I removed the confusing Windows/Linux distinction. It serves no real goal in the documentation, and is probably wrong anyway since for Windows the WINFUNCTYPE constructor should be used. In addition, the "look, this is faster on Linux" comment is misleading since it's not explained. The outcome may just be an artifact of qsort implementation for this particular input, and may change between C runtime version releases.
1 parent 3405001 commit 2a1e74a

1 file changed

Lines changed: 14 additions & 80 deletions

File tree

Doc/library/ctypes.rst

Lines changed: 14 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -926,21 +926,21 @@ Callback functions
926926
:mod:`ctypes` allows to create C callable function pointers from Python callables.
927927
These are sometimes called *callback functions*.
928928

929-
First, you must create a class for the callback function, the class knows the
929+
First, you must create a class for the callback function. The class knows the
930930
calling convention, the return type, and the number and types of arguments this
931931
function will receive.
932932

933-
The CFUNCTYPE factory function creates types for callback functions using the
934-
normal cdecl calling convention, and, on Windows, the WINFUNCTYPE factory
935-
function creates types for callback functions using the stdcall calling
936-
convention.
933+
The :func:`CFUNCTYPE` factory function creates types for callback functions
934+
using the ``cdecl`` calling convention. On Windows, the :func:`WINFUNCTYPE`
935+
factory function creates types for callback functions using the ``stdcall``
936+
calling convention.
937937

938938
Both of these factory functions are called with the result type as first
939939
argument, and the callback functions expected argument types as the remaining
940940
arguments.
941941

942942
I will present an example here which uses the standard C library's
943-
:c:func:`qsort` function, this is used to sort items with the help of a callback
943+
:c:func:`qsort` function, that is used to sort items with the help of a callback
944944
function. :c:func:`qsort` will be used to sort an array of integers::
945945

946946
>>> IntArray5 = c_int * 5
@@ -953,44 +953,16 @@ function. :c:func:`qsort` will be used to sort an array of integers::
953953
items in the data array, the size of one item, and a pointer to the comparison
954954
function, the callback. The callback will then be called with two pointers to
955955
items, and it must return a negative integer if the first item is smaller than
956-
the second, a zero if they are equal, and a positive integer else.
956+
the second, a zero if they are equal, and a positive integer otherwise.
957957

958958
So our callback function receives pointers to integers, and must return an
959959
integer. First we create the ``type`` for the callback function::
960960

961961
>>> CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
962962
>>>
963963

964-
For the first implementation of the callback function, we simply print the
965-
arguments we get, and return 0 (incremental development ;-)::
966-
967-
>>> def py_cmp_func(a, b):
968-
... print("py_cmp_func", a, b)
969-
... return 0
970-
...
971-
>>>
972-
973-
Create the C callable callback::
974-
975-
>>> cmp_func = CMPFUNC(py_cmp_func)
976-
>>>
977-
978-
And we're ready to go::
979-
980-
>>> qsort(ia, len(ia), sizeof(c_int), cmp_func) # doctest: +WINDOWS
981-
py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>
982-
py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>
983-
py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>
984-
py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>
985-
py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>
986-
py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>
987-
py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>
988-
py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>
989-
py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>
990-
py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>
991-
>>>
992-
993-
We know how to access the contents of a pointer, so lets redefine our callback::
964+
To get started, here is a simple callback that shows the values it gets
965+
passed::
994966

995967
>>> def py_cmp_func(a, b):
996968
... print("py_cmp_func", a[0], b[0])
@@ -999,23 +971,7 @@ We know how to access the contents of a pointer, so lets redefine our callback::
999971
>>> cmp_func = CMPFUNC(py_cmp_func)
1000972
>>>
1001973

1002-
Here is what we get on Windows::
1003-
1004-
>>> qsort(ia, len(ia), sizeof(c_int), cmp_func) # doctest: +WINDOWS
1005-
py_cmp_func 7 1
1006-
py_cmp_func 33 1
1007-
py_cmp_func 99 1
1008-
py_cmp_func 5 1
1009-
py_cmp_func 7 5
1010-
py_cmp_func 33 5
1011-
py_cmp_func 99 5
1012-
py_cmp_func 7 99
1013-
py_cmp_func 33 99
1014-
py_cmp_func 7 33
1015-
>>>
1016-
1017-
It is funny to see that on linux the sort function seems to work much more
1018-
efficiently, it is doing less comparisons::
974+
The result::
1019975

1020976
>>> qsort(ia, len(ia), sizeof(c_int), cmp_func) # doctest: +LINUX
1021977
py_cmp_func 5 1
@@ -1025,32 +981,13 @@ efficiently, it is doing less comparisons::
1025981
py_cmp_func 1 7
1026982
>>>
1027983

1028-
Ah, we're nearly done! The last step is to actually compare the two items and
1029-
return a useful result::
984+
Now we can actually compare the two items and return a useful result::
1030985

1031986
>>> def py_cmp_func(a, b):
1032987
... print("py_cmp_func", a[0], b[0])
1033988
... return a[0] - b[0]
1034989
...
1035990
>>>
1036-
1037-
Final run on Windows::
1038-
1039-
>>> qsort(ia, len(ia), sizeof(c_int), CMPFUNC(py_cmp_func)) # doctest: +WINDOWS
1040-
py_cmp_func 33 7
1041-
py_cmp_func 99 33
1042-
py_cmp_func 5 99
1043-
py_cmp_func 1 99
1044-
py_cmp_func 33 7
1045-
py_cmp_func 1 33
1046-
py_cmp_func 5 33
1047-
py_cmp_func 5 7
1048-
py_cmp_func 1 7
1049-
py_cmp_func 5 1
1050-
>>>
1051-
1052-
and on Linux::
1053-
1054991
>>> qsort(ia, len(ia), sizeof(c_int), CMPFUNC(py_cmp_func)) # doctest: +LINUX
1055992
py_cmp_func 5 1
1056993
py_cmp_func 33 99
@@ -1059,9 +996,6 @@ and on Linux::
1059996
py_cmp_func 5 7
1060997
>>>
1061998

1062-
It is quite interesting to see that the Windows :func:`qsort` function needs
1063-
more comparisons than the linux version!
1064-
1065999
As we can easily check, our array is sorted now::
10661000

10671001
>>> for i in ia: print(i, end=" ")
@@ -1071,9 +1005,9 @@ As we can easily check, our array is sorted now::
10711005

10721006
**Important note for callback functions:**
10731007

1074-
Make sure you keep references to CFUNCTYPE objects as long as they are used from
1075-
C code. :mod:`ctypes` doesn't, and if you don't, they may be garbage collected,
1076-
crashing your program when a callback is made.
1008+
Make sure you keep references to :func:`CFUNCTYPE` objects as long as they are
1009+
used from C code. :mod:`ctypes` doesn't, and if you don't, they may be garbage
1010+
collected, crashing your program when a callback is made.
10771011

10781012

10791013
.. _ctypes-accessing-values-exported-from-dlls:

0 commit comments

Comments
 (0)