Differences in ctypes between Python 2 and 3

In our case, we had code looking like:

addr = clib.some_function()
data = some_struct.from_address(addr)

This worked in python 2 but not in 3. The reason turned out not to be any difference in ctypes, but rather a change in memory layout that unmasked a bug in the code above. In python 2, the address returned was always (by chance) small enough to fit inside a C int (32-bit), which is the default return type for all ctypes function calls. In python 3, the addresses were almost always too large, which caused the pointer address to become corrupted as it was coerced to int.

The solution is to set the function restype to a 64-bit integer type to ensure that it can accommodate the whole address, like:

clib.some_function.restype = c_longlong

or:

clib.some_function.restype = POINTER(some_struct)

In Python 2.7, strings are byte-strings by default. In Python 3.x, they are unicode by default. Try explicitly making your string a byte string using .encode('ascii') before handing it to DLL.prepare.

Edit:

#another way of saying table=str(aNumber).encode('ascii')
table = bytes(str(aNumber), 'ascii')
DLL.prepare(table)