[Tutor] Help with using the ctypes module
Luke Paireepinart
rabidpoobear at gmail.com
Mon Dec 13 21:54:05 CET 2010
I confess I don't know a lot about C so I may be off base here... But it looks like your c func extendarray returns a pointer to the new extended array, but you are not capturing this pointer in your python when you call the c func. So the python code is pointing at the old deallocated array.
Does that make sense and/or point you in the right direction?
-----------------------------
Sent from a mobile device with a bad e-mail client.
-----------------------------
On Dec 13, 2010, at 10:27 AM, Sachin Kamboj <backslash42 at gmail.com> wrote:
> Hi All,
>
> I was trying to use the ctypes module for a project. I was creating a dynamically allocated array of "max_entries" pairs and once the array was exhausted, I was creating a new array of size (1.5 * max_entries) and copying the contents from the old array to the new array.
>
> Unfortunately, when I try to access the contents of this new_array, I get a "NULL pointer access" exception. The corresponding C code seems to work perfectly. (See code below.)
>
> I was wondering if I was missing something about the way the ctypes module works. Any help would be greatly appreciated. (Not sure if this is the appropriate mailing list for my question.)
>
> /Thanks!
>
> ---
>
> #!/usr/bin/env python
>
> from ctypes import *
> import math
> import random
>
>
> class PAIR(Structure):
> _fields_ = [("a", c_long),
> ("b", c_long)]
>
>
> class MY_ARR(Structure):
> _fields_ = [("no_entries", c_longlong),
> ("max_entries", c_longlong),
> ("entries", POINTER(POINTER(PAIR)))
> ]
>
> def extendArray(x):
> print "Extending Array"
> print "Before: %d/%d" % (x.no_entries, x.max_entries)
> old_arr = x.entries
>
> # Create a new array
> new_max_entries = int(math.ceil(1.5 * x.max_entries))
> x.entries = (POINTER(PAIR) * new_max_entries)()
>
> # Copy the entries from the old array to the new array
> for i in range(x.no_entries):
> x.entries[i] = old_arr[i]
>
> x.max_entries = new_max_entries
> print "After: %d/%d" % (x.no_entries, x.max_entries)
> return x
>
> def printPair(x):
> print x.contents.a, x.contents.b
>
> def printArray(x):
> print "Printing %d/%d Entries" % (x.no_entries, x.max_entries)
> for i in range(x.no_entries):
> printPair(x.entries[i])
>
>
> if __name__ == "__main__":
> x = MY_ARR(0, 10, (POINTER(PAIR) * 10)())
> for i in range(100):
> if x.no_entries == x.max_entries:
> print "\n\nPrinting Before Extension"
> printArray(x)
>
> extendArray(x)
>
> print "\n\nPrinting After Extension"
> printArray(x)
>
> my_pair = PAIR(i, random.randint(0, 100))
> x.entries[x.no_entries] = pointer(my_pair)
> x.no_entries += 1
>
> printPair(x.entries[i])
>
> printArray(x)
>
> ---
> Now unfortunately, when I try to run this code, I am getting a "NULL pointer access" exception:
>
> $ python TestExtension.py
> 0 40
> 1 40
> 2 11
> 3 36
> 4 82
> 5 73
> 6 93
> 7 100
> 8 75
> 9 80
>
>
> Printing Before Extension
> Printing 10/10 Entries
> 0 40
> 1 40
> 2 11
> 3 36
> 4 82
> 5 73
> 6 93
> 7 100
> 8 75
> 9 80
> Extending Array
> Before: 10/10
> After: 10/15
>
>
> Printing After Extension
> Printing 10/15 Entries
> Traceback (most recent call last):
> File "TestExtension.py", line 55, in <module>
> printArray(x)
> File "TestExtension.py", line 42, in printArray
> printPair(x.entries[i])
> File "TestExtension.py", line 37, in printPair
> print x.contents.a, x.contents.b
> ValueError: NULL pointer access
>
> ---
>
> The corresponding C code works perfectly:
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <math.h>
>
> typedef struct {
> long a;
> long b;
> } pair;
>
> typedef struct {
> long long no_entries;
> long long max_entries;
> pair **entries;
> } my_arr;
>
> my_arr *extend_array(my_arr *x) {
> int i;
> pair **old_entries = x->entries;
> long long new_max_entries = ceil(1.5 * x->max_entries);
>
> printf("Extending Array\n");
> printf("Before: %lld/%lld\n", x->no_entries, x->max_entries);
>
> x->entries = malloc(sizeof(pair *) * new_max_entries);
> for (i = 0; i < 100; ++i) {
> x->entries[i] = old_entries[i];
> }
> x->max_entries = new_max_entries;
> free(old_entries);
>
> printf("After: %lld/%lld\n", x->no_entries, x->max_entries);
> return x;
> }
>
> void print_pair(pair *p) {
> printf("%ld\t%ld\n", p->a, p->b);
> }
>
> void print_array(my_arr *x) {
> int i;
> printf("Printing %lld/%lld entries\n", x->no_entries, x->max_entries);
> for (i = 0; i < x->no_entries; ++i) {
> print_pair(x->entries[i]);
> }
> }
>
> int main(int argc, char *argv[])
> {
> int i;
> my_arr x = {
> 0,
> 10,
> malloc(sizeof(pair *) * 10)
> };
>
> for (i = 0; i < 100; ++i) {
> if (x.no_entries == x.max_entries) {
> extend_array(&x);
> }
> pair *my_pair = malloc(sizeof(pair));
> my_pair->a = i;
> my_pair->b = rand() % 100;
>
> x.entries[x.no_entries++] = my_pair;
> print_pair(x.entries[i]);
> }
> print_array(&x);
> return 0;
> }
>
>
> _______________________________________________
> Tutor maillist - Tutor at python.org
> To unsubscribe or change subscription options:
> http://mail.python.org/mailman/listinfo/tutor
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tutor/attachments/20101213/56e94551/attachment-0001.html>
More information about the Tutor
mailing list