tags:

views:

66

answers:

1
import ctypes

a = 'abc'
b = ctypes.string_at(id(a), 3)
c = ctypes.string_at(id(a) + 20, 3)

I expect the result of b to be 'abc', but it is not; and the result of c is 'abc'. I don't know why. Anyone can explain me?

+5  A: 

In Python, a str is an object, so there is no guarantee about what it looks like in memory. Probably, it contains some more information, like the length of the string. In your case, the size of this "metadata" is apparently 20 bytes.

Possibly, the object itself does not even contain the actual string, but rather a pointer to it. If that is the case, in your situation the actual string happens to be located 20 bytes after the object.

Either way, this is an implementation detail. None of this behaviour should be relied upon in any serious code.

Thomas
Exactly right. In Python 2.6 the metadata consist of: (1) a pointer to the object type, (2) the reference count, (3) the size of the string, (4) a cached value for the hash of the object, and (5) a flag indicating whether this string is interned or not. At 4 bytes for each of these fields (on a 32-bit machine), this explains the 20-byte offset.
Mark Dickinson
then is there any way to access the memory of a string?
zhanwu
@Mark Dickinson, so I can always have the buffer if I do the 20-byte offset? it is not just happen that 20 work for me once, and next it will not, right?
zhanwu
Next time you run your code on some other Python version, or another machine, or another operating system, it is likely to break. Why do you want to access this memory in the first place?
Thomas
@Thomasmy problem is actually I want to display a numpy matrix as a pyglet image, so I try to use "pyglet.image.ImageData()" function to create a pyglet image. This function require the pixel data(in my case the matrix data) as an input. So I try to convert the numpy matrix to string, and then get the memory of the string, then pass it to the "pyglet.image.ImageData()" function.This is the whole story
zhanwu
The `ImageData()` constructor also accepts a list of bytes. You can use `tolist()` on your numpy matrix , concatenate that list, convert its elements to bytes, then feed it to the `ImageData` constructor. Slower, but if you wanted blazing speed, you'd not be using Python in the first place.
Thomas