2

I need to access the contents of a char* by casting it to an array

Here's a demo:

from ctypes import *

foo = (c_char * 4)()
foo.value = "foo"
print foo.raw # => 'foo\x00'
foo_ptr = cast(foo, c_char_p)
print foo_ptr.value # => 'foo'

Now I want to convert foo_ptr back into a (c_char * 4). Neither of these work

foo_ = (c_char * 4)(foo_ptr)
foo_ = cast(foo_ptr, c_char * 4)
Eryk Sun
  • 33,190
  • 5
  • 92
  • 111
chriso
  • 2,552
  • 1
  • 20
  • 16

2 Answers2

5

Found it

foo_ = (c_char * 4).from_address(foo_ptr._get_buffer_value())

print foo_.raw # => 'foo\x00'
chriso
  • 2,552
  • 1
  • 20
  • 16
  • This may be old as `_get_buffer_value` doesn't seem to exist. Even if it did, the initial underscore suggests that it's an internal function. [This answer](http://stackoverflow.com/a/9784508/912144) is better. – Shahbaz Mar 27 '15 at 15:34
1

Why don't you keep the original foo?:

>>> foo = (c_char * 4)()
>>> foo_ptr_1 = ct.cast( foo, ct.c_char_p )
>>> foo_ptr_1
c_char_p(28211760)
>>> foo_ptr_2 = ct.cast( foo, ct.c_char_p )
>>> foo_ptr_2
c_char_p(28211760)

so the cast operation doesn't copy the data, but merely returns a pointer to the array's contents. You can also index through the pointer, although that's slightly unsafer.

Alternatively, if you want to create the array de novo, do the following:

>>> array_type = (c_char * 4 )
>>> foo = array_type.from_address( foo_ptr )
>>> foo.value
'abc'
dsign
  • 12,340
  • 6
  • 59
  • 82
  • It was just an example. In my actual code I don't have access to an array, just a pointer and length – chriso Jul 07 '12 at 05:30