On Thu, May 5, 2016 at 10:42 AM, Joseph L. Casale
<jcas...@activenetwerx.com> wrote:
> I have CDLL function I use to get a pointer, several other functions happily 
> accept this
> pointer which is really a long when passed to ctypes.c_void_p. However, only 
> one with
> same type def in the prototype overflows. Docs suggest c_void_p takes an int 
> but that
> is not what the first call returns, nor what all but one function happily 
> accept?

What you're describing isn't clear to me, so I'll describe the general
case of handling pointers with ctypes functions. If a function returns
a pointer, you must set the function's restype to a pointer type since
the default c_int restype truncates the upper half of a 64-bit
pointer. Generally you also have to do the same for pointer parameters
in argtypes. Otherwise integer arguments are converted to C int
values.

Note that when restype is set to c_void_p, the result gets converted
to a Python integer (or None for a NULL result). If you pass this
result back as a ctypes function argument, the function must have the
parameter set to c_void_p in argtypes. If argtypes isn't set, the
default integer conversion may truncate the pointer value. This
problem won't occur on a 32-bit platform, so there's a lot of
carelessly written ctypes code that makes this mistake.

Simple types are also automatically converted when accessed as a field
of a struct or union or as an index of an array or pointer. To avoid
this, you can use a subclass of the type, since ctypes won't
automatically convert subclasses of simple types.

I generally avoid c_void_p because its lenient from_param method
(called to convert arguments) doesn't provide much type safety. If a
bug causes an incorrect argument to be passed, I prefer getting an
immediate ctypes.ArgumentError rather than a segfault or data
corruption. For example, when a C API returns a void pointer as a
handle for an opaque structure or object, I prefer to handle it as a
pointer to an empty Structure subclass, as follows:

    class _ContosoHandle(ctypes.Structure):
        pass

    ContosoHandle = ctypes.POINTER(_ContosoHandle)

    lib.CreateContoso.restype = ContosoHandle
    lib.DestroyContoso.argtypes = (ContosoHandle,)

ctypes will raise an ArgumentError if DestroyContoso is called with
arguments such as 123456789 or "Crash Me".
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to