Prev: Hi, friends. I wanna ask if there is a function which is ableto take a list as argument and then return its top-k maximums?
Next: Tkinter question
From: Zvezdan Petkovic on 22 Apr 2010 10:49 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 > _string_destroy(tmp_char_ptr) > return prop_val Is this what you want? ===== import ctypes.util 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) def strdup_and_free(s): s_ptr = libc.strdup(s) print s_ptr.contents i = 0 while s_ptr[i] != '\0': print s_ptr[i], i += 1 libc.free(s_ptr) if __name__ == '__main__': strdup_and_free('My string') ===== That is an equivalent of this C program: ===== #include <stdio.h> #include <stdlib.h> #include <string.h> void strdup_and_free(char *s) { char *s_ptr = strdup(s); printf("%c\n", *s_ptr); printf("%s\n", s_ptr); free(s_ptr); } int main(int argc, char *argv[]) { strdup_and_free("My string"); return 0; } ===== 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. Best regards, Zvezdan > > On Wed, Apr 21, 2010 at 3:15 PM, Brendan Miller <catphive(a)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 >> doubt. >> >> 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? >> >> Thanks >> Brendan >> > -- > http://mail.python.org/mailman/listinfo/python-list
From: Zvezdan Petkovic on 22 Apr 2010 12:18 On Apr 22, 2010, at 10:49 AM, Zvezdan Petkovic wrote: > libc.strdup.argtype = [ctypes.c_char_p] Correcting my typo. This should be in plural: libc.strdup.argtypes = [ctypes.c_char_p]
From: Brendan Miller on 22 Apr 2010 17:34
On Thu, Apr 22, 2010 at 7:49 AM, Zvezdan Petkovic <zvezdan(a)zope.com> wrote: > > 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 >> _string_destroy(tmp_char_ptr) >> return prop_val > > Is this what you want? > > ===== > > import ctypes.util > > > 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) > > > def strdup_and_free(s): > s_ptr = libc.strdup(s) > print s_ptr.contents > i = 0 > while s_ptr[i] != '\0': > print s_ptr[i], > i += 1 > libc.free(s_ptr) Ah, so c_char_p's are converted to python strings by ctypes, but POINTER(c_char) is *not*. Thanks |