ctypes: delay conversion from c_char_p to string
zvezdan at zope.com
Thu Apr 22 16:49:23 CEST 2010
On Apr 21, 2010, at 6:29 PM, Brendan Miller wrote:
> Here's the method I was using. Note that tmp_char_ptr is of type
> c_void_p. This should avoid the memory leak, assuming I am
> interpreting the semantics of the cast correctly. Is there a cleaner
> way to do this with ctypes?
> def get_prop_string(self, prop_name):
> # Have to work with c_void_p to prevent ctypes from copying to a string
> # without giving me an opportunity to destroy the original string.
> tmp_char_ptr = _get_prop_string(self._props, prop_name)
> prop_val = cast(tmp_char_ptr, c_char_p).value
> return prop_val
Is this what you want?
libc = ctypes.CDLL(ctypes.util.find_library('libc'))
libc.free.argtypes = [ctypes.c_void_p]
libc.free.restype = None
libc.strdup.argtype = [ctypes.c_char_p]
libc.strdup.restype = ctypes.POINTER(ctypes.c_char)
s_ptr = libc.strdup(s)
i = 0
while s_ptr[i] != '\0':
i += 1
if __name__ == '__main__':
That is an equivalent of this C program:
char *s_ptr = strdup(s);
main(int argc, char *argv)
To prove that the pointer was actually freed try inserting one more
libc.free(s_ptr) at the end of the function.
You should get Abort trap because you are attempting to free storage that has already been freed (I did on Mac OS X 10.6)
If you insert a second free(s_ptr) call in the C program you also get an Abort trap:
strdup2(15785) malloc: *** error for object 0x100100080: pointer being freed was not allocated
(Again, this is an error message on Mac OS X 10.6)
FWIW, this technique for getting pointer *is* mentioned in ctypes documentation.
> On Wed, Apr 21, 2010 at 3:15 PM, Brendan Miller <catphive at catphive.net> wrote:
>> I have a function exposed through ctypes that returns a c_char_p.
>> Since I need to deallocate that c_char_p, it's inconvenient that
>> ctypes copies the c_char_p into a string instead of giving me the raw
>> pointer. I believe this will cause a memory leak, unless ctypes is
>> smart enough to free the string itself after the copy... which I
>> Is there some way to tell ctypes to return an actual c_char_p, or is
>> my best bet to return a c_void_p and cast to c_char_p when I'm reading
>> to convert to a string?
More information about the Python-list