This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: from_param and _as_parameter_ truncating 64-bit value
Type: Stage:
Components: Library (Lib) Versions:
process
Status: closed Resolution: works for me
Dependencies: Superseder:
Assigned To: theller Nosy List: albertstrasheim, loewis, sjvdw, theller
Priority: normal Keywords:

Created on 2006-10-12 14:25 by albertstrasheim, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (7)
msg30215 - (view) Author: Albert Strasheim (albertstrasheim) Date: 2006-10-12 14:25
There seems to be something strange going on with
ctypes' _as_parameter_ on 64-bit machines. I haven't
been able to replicate this problem without NumPy, but
it looks like a ctypes issue since NumPy's
_as_parameter_ contains a valid value but the value
that arrives in the C function has had its upper 4
bytes zeroed.

SConstruct to build library:

env = Environment()
env.Replace(CCFLAGS=['-O0','-ggdb','-Wall','-ansi','-pedantic'])
env.SharedLibrary('spfuncs',['spfuncs.c'])

C code:

#include <stdio.h>
void nnz(double *ary) {
    printf("ary = %p\n", (void*)ary);
}

Python code:

import numpy as N
from ctypes import *
from numpy.ctypeslib import ndpointer
_libspfuncs = N.ctypeslib.load_library('libspfuncs',
__file__) _libspfuncs.nnz.restype  = None A =
N.eye((128)) print 'data_as',
A.ctypes.data_as(c_void_p) print 'array interface',
hex(A.__array_interface__['data'][0])
_libspfuncs.nnz.argtypes = [POINTER(c_double)]
_libspfuncs.nnz(A.ctypes.data_as(POINTER(c_double)))
_libspfuncs.nnz.argtypes = [ndpointer(dtype = N.float64)]
_libspfuncs.nnz(A)
print '_as_parameter', hex(A.ctypes._as_parameter_)

Output on 32-bit system:

data_as c_void_p(-1212006392)
array interface -0x483dbff8
ary = 0xb7c24008
ary = 0xb7c24008
_as_parameter -0x483dbff8

Output on 64-bit system:

data_as c_void_p(46912559644688)
array interface 0x2aaaae740010
ary = 0x2aaaae740010
ary = 0xae740010
_as_parameter 0x2aaaae740010
msg30216 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2006-10-14 20:07
Logged In: YES 
user_id=21627

Thomas, can you take a look? If not, please unassign.
msg30217 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2006-10-16 15:05
Logged In: YES 
user_id=11105

This is not a ctypes bug.

It seems that A.ctypes._as_parameter_ is a Python integer. 
These are passed as 'C int' type to foreign function calls.
(The C int type typically has 32 bits on 64-bit platforms,
while a pointer has 64 bit.)

To pass a pointer, A.ctypes._as_parameter_ should be a
ctypes c_void_p instance, not a Python integer.
msg30218 - (view) Author: Albert Strasheim (albertstrasheim) Date: 2006-10-16 16:18
Logged In: YES 
user_id=945096

Changing NumPy's _as_parameter_ to return the pointer as a
c_void_p causes ctypes to raise the following erorr:

ctypes.ArgumentError: argument 1: exceptions.TypeError:
Don't know how to convert parameter 1
msg30219 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2006-10-17 17:48
Logged In: YES 
user_id=11105

I replaced in numpy/core/_internal.py, version 1.0rc2, the
get_as_parameter method with this code:

    def get_as_parameter(self):
        ##return self._data
        return self._ctypes.c_void_p(self._data)

and here is the script and the output on a 64-bit Linux
system, with Python 2.5:

theller@tubu:~/devel/release25-maint$ cat param.py
import numpy
from numpy.ctypeslib import ndpointer
from ctypes import *
import _ctypes_test

A = numpy.eye(1280)

print A.__array_interface__['data'],
hex(A.__array_interface__['data'][0])

func = CDLL(_ctypes_test.__file__)._testfunc_p_p
func.restype = c_void_p
func.argtypes = [ndpointer(dtype=numpy.float64)]

print hex(func(A))
theller@tubu:~/devel/release25-maint$ ./python param.py
(46912527945744, False) 0x2aaaac905010
0x2aaaac905010
theller@tubu:~/devel/release25-maint$


As you can see the 64-bit pointer is passed through the
function.  _testfunc_p_p in _ctypes_test.so is simply

char * _testfunc_p_p (void *s)
{
    return (char *)s;
}
msg30220 - (view) Author: Stefan van der Walt (sjvdw) Date: 2006-10-18 01:40
Logged In: YES 
user_id=1104792

On both 32 and 64-bit systems, running param.py under python
2.4 with ctypes 1.0.0 and numpy from SVN (with patch
applied) I see:

$ python param.py 
(-1264099320, False)
Traceback (most recent call last):
  File "param.py", line 16, in ?
    print hex(func(A))
ctypes.ArgumentError: argument 1: exceptions.TypeError:
Don't know how to convert parameter 1

msg30221 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2006-10-19 17:17
Logged In: YES 
user_id=11105

This is a ctypes 1.0.0 bug then ;-).

Python 2.5 contains ctypes 1.0.1, which is not yet released
as standalone package, but I'll do it ASAP.

Therefore I'll close this report as 'works for me', please
reopen if it still does not work with Python 2.4 and ctypes
1.0.1.
History
Date User Action Args
2022-04-11 14:56:20adminsetgithub: 44117
2006-10-12 14:25:17albertstrasheimcreate