classification
Title: ctypes callback fails when called in Python with array argument
Type: behavior Stage: patch review
Components: Library (Lib), Windows Versions: Python 3.2, Python 3.3
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: theller Nosy List: belopolsky, kermode, theller
Priority: normal Keywords: needs review, patch

Created on 2008-01-11 23:14 by kermode, last changed 2014-02-03 19:42 by BreamoreBoy.

Files
File name Uploaded Description Edit
issue1800.diff belopolsky, 2010-05-17 17:12 Patch for trunk
issue1800.diff kermode, 2010-09-20 18:55 revised patch to r84925 (py3k)
Messages (6)
msg59759 - (view) Author: Lenard Lindstrom (kermode) Date: 2008-01-11 23:14
When a callback is created with an array argument and then is called
from Python the callback function receives an array full of garbage.

Here is an example:

Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit
(Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *
>>> A = c_int * 1
>>> A
<class '__main__.c_long_Array_1'>
>>> Foo = CFUNCTYPE(None, A)
>>> def py_foo(a):
...     print a
...     print a[0]
...
>>> foo = Foo(py_foo)
>>> foo(A(42))
<__main__.c_long_Array_1 object at 0x00B54440>
11879448

It works correctly when the callback is declared with a pointer argument
instead:

>>> A = c_int * 1
>>> Foo = CFUNCTYPE(None, POINTER(c_int))
>>> def py_foo(p):
...     print p
...     print p[0]
...
>>> foo = Foo(py_foo)
>>> foo(A(42))
<ctypes.LP_c_long object at 0x00B54440>
42
msg105916 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-05-17 17:12
Attached patch fixes the issue, but feels a little bit like a band-aid. I think making array arguments "decay" into pointers is the right solution, but I am not sure this should be done when prototype is created or when it is called.  If python level solution is accepted, a better way to detect an array type should probably be found.
msg110597 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2010-07-17 19:13
This is a very small patch against the ctypes __init__.py, could anyone with some ctypes experience please review the patch.
msg116865 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2010-09-19 11:24
Anybody?
msg116875 - (view) Author: Lenard Lindstrom (kermode) Date: 2010-09-19 16:08
I will check it out.
msg116962 - (view) Author: Lenard Lindstrom (kermode) Date: 2010-09-20 18:55
I have checked over the proposed patch and made a small change that more elegantly obtains PyCArrayType. Decaying arrays into pointers is not an ideal solution. Ctypes arrays have bounds checking (pointers do not) adding an extra margin of safety when a C function prototype has sized arrays in the declaration. But this is a rare case. So the proposed patch is good enough. The alternative is to reject arrays as arguments altogether, with CFUNCTYPE raising an exception if one is found.

The problem lies with line 1241 in _ctypes.c and line 221 in callbacks.c (r84925 or py3k). In the first case, the value of CDataObject.b_ptr is assigned to PyCArgObject.value.p. In the second case PyCArgObject.value.p (*pArgs) is recovered to *CDataObject.b_ptr. I see no way to fix this without changes to several functions and files.
History
Date User Action Args
2014-02-03 19:42:08BreamoreBoysetnosy: - BreamoreBoy
2010-09-20 18:55:10kermodesetfiles: + issue1800.diff

messages: + msg116962
2010-09-19 16:08:28kermodesetmessages: + msg116875
2010-09-19 11:24:21BreamoreBoysetmessages: + msg116865
2010-07-17 19:13:28BreamoreBoysetnosy: + BreamoreBoy
messages: + msg110597
2010-05-17 17:13:38belopolskysetkeywords: + needs review
stage: test needed -> patch review
2010-05-17 17:12:49belopolskysetfiles: + issue1800.diff
keywords: + patch
messages: + msg105916
2010-05-17 15:00:31belopolskysetnosy: + belopolsky
stage: test needed

versions: + Python 3.2, Python 3.3, - Python 2.5
2008-01-12 00:04:28christian.heimessetpriority: normal
assignee: theller
nosy: + theller
2008-01-11 23:14:58kermodecreate