Ok, I've made some progress thanks to Tye, however, I've gotten myself more
frustrated than ever at trying to figure out what's up with this xsub stuff.
For example, If I run this : 

$s = Image::Rmap::newImageLayout(500,500,0);
$o = Image::Rmap::newOptions(1,1,20,30,-100,0, "/usr/local/share/rmap/earth.rez", 
"/tmp/outfile.gif", "/home/reza/projects/rmap/rmap.colors", 0xFFFFFFFF,0xFFFFFFFF);
$o->show();
Image::Rmap::generate($s,$o);

where $o is an Image::Rmap::Options defined as a T_PTROBJ which is a pointer
to this struct : 

struct options
{
  int cities;
  int gridlines;
  double zoom;
  double xrot;
  double yrot;
  double zrot;
  char* mapfile;
  char* outfile;
  char* colorfile;
  BIT32 desired_categories;
  BIT32 desired_continents;
};

and Image::Rmap::Options::show() just does a printf on the mapfile, outfile,
and colorfile.

it works (though segfaults in the garbage collection).  If I add one more
line to the code (after the generate) ..

.snip..
$o->show();
Image::Rmap::generate($s,$o); 
$o->show();

then somehow, the mapfile element of the struct becomes NULL, though
everything else if fine (this happens by the time the first show turns up).  

I've also stuck in the appropriate  DESTROY functions.  If I try to free the
object myself, it segfaults, but if I don't, then when the perl code is done
running, somehow in the garbage collecting, it dies (I know this is ugly, but
this is the stack trace before it dies)..

(this is with just one $o->show() )
(gdb) bt
#0  0x400bdee9 in chunk_free (ar_ptr=0x40152040, p=0x80c7690) at
malloc.c:3047
#1  0x400bdd75 in __libc_free (mem=0x80c7698) at malloc.c:2959
#2  0x807ae2c in Perl_safefree ()
#3  0x808c4ef in Perl_sv_clear ()
#4  0x808c5aa in Perl_sv_free ()
#5  0x8073e9a in Perl_cv_undef ()
#6  0x808c3c2 in Perl_sv_clear ()
#7  0x808c5aa in Perl_sv_free ()
#8  0x80574c4 in perl_destruct ()
#9  0x8056beb in main ()


(and this is with two show()s) 
(gdb) bt
#0  0x400bdee9 in chunk_free (ar_ptr=0x40152040, p=0x80cbf68) at
malloc.c:3047
#1  0x400bdd75 in __libc_free (mem=0x80cbf70) at malloc.c:2959
#2  0x807ae2c in Perl_safefree ()
#3  0x806f650 in Perl_op_free ()
#4  0x806f531 in Perl_op_free ()
#5  0x8057498 in perl_destruct ()
#6  0x8056beb in main ()

I'de love to figure out what the hell perl is doing and adding a simple print
statement inside the perl code makes my stuff work all differently.  If
anyone can provide any advice, it would be most helpful.  

Thanks in advance,
Reza

p.s. here's the code so far (as I have it)

#ifdef __cplusplus
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#ifdef __cplusplus
}
#endif

#include "rgb.h"
#include <gd.h>

#define BIT32 int
#define NOPRINT -1

struct imageLayout
{
  int height;                   //y
  int width;                    //x
  short transparent;
  gdImagePtr im;
  int colormap[5][16];
};

struct options 
{
  int cities;
  int gridlines;
  double zoom;
  double xrot;
  double yrot;
  double zrot;
  char* mapfile;
  char* outfile;
  char* colorfile;
  BIT32 desired_categories;
  BIT32 desired_continents; 
};

/* some more stuff */
extern void generate(struct imageLayout *scene, struct options *o);
extern struct color* get_color (char* c);
typedef struct imageLayout* Image__Rmap__Scene;
typedef struct options* Image__Rmap__Options;

MODULE = Image::Rmap            PACKAGE = Image::Rmap

Image::Rmap::Scene 
newImageLayout(height, width, transparent)
        int height;
        int width;
        int transparent;
        PROTOTYPE: $$$
        CODE:
                RETVAL = safemalloc (sizeof(RETVAL));
                if (RETVAL == NULL) 
                        croak("safemalloc() returned NULL in 
Image::Rmap::newImageLayout().\n"); 
                RETVAL->height = height;
                RETVAL->width  = width;
                RETVAL->transparent  = transparent;
                RETVAL->im = gdImageCreate(width, height);
        OUTPUT:
                RETVAL


MODULE = Image::Rmap            PACKAGE = Image::Rmap::Scene    

void
DESTROY(scene)
        Image::Rmap::Scene scene;
        PROTOTYPE: $
        CODE:
        {
                printf("Image::Rmap::Scene::DESTROY called\n");
                gdImageDestroy(scene->im);
//              safefree(scene);
                printf("Image::Rmap::Scene::DESTROY finished\n");
        }


MODULE = Image::Rmap            PACKAGE = Image::Rmap::Scene    

void
setColor(scene, catagory, type, color_name)
        Image::Rmap::Scene scene;
        int catagory;
        int type;
        char* color_name;
        PROTOTYPE: $$$$
        CODE:
        {
                struct color *c;
                if (!strcmp(color_name, "none")) {
                        scene->colormap[catagory][type] = NOPRINT;
                } else {
                        if (catagory > 4 || type > 15 || catagory < 0 || type < 0) {
                                croak("Declaration value out of range (%d,%d).", 
catagory,type);
                        } else {
                                c =  get_color(color_name);
                                if (c == NULL)  {
                                        croak("The color %s was not found", 
color_name);
                                } else {
                                        scene->colormap[catagory][type] = 
                                                gdImageColorAllocate(scene->im, c->r, 
c->g, c->b);
                                }
                        }
                }
        }

MODULE = Image::Rmap            PACKAGE = Image::Rmap

Image::Rmap::Options
newOptions(cities, gridlines, zoom, xrot, yrot, zrot, mapfile, outfile, colorfile, 
des_cat, des_cont)
        int cities;
        int gridlines;
        double zoom;
        double xrot;
        double yrot;
        double zrot;
        char* mapfile;
        char* outfile;
        char* colorfile;
        int des_cat;
        int des_cont;
        PROTOTYPE: $$$$$$$$$$$
        CODE:
        {
                RETVAL = safemalloc (sizeof(RETVAL));

                if (RETVAL == NULL) 
                        croak("safemalloc() returned NULL in 
Image::Rmap::newOptions().\n"); 

                RETVAL->mapfile = RETVAL->outfile = RETVAL->colorfile = NULL;

                if (mapfile) 
                        if ((RETVAL->mapfile = strdup(mapfile)) == NULL) 
                                croak("strdup() returned NULL in 
Image::Rmap::newOptions() for mapfile\n");
                if (outfile)
                        if ((RETVAL->outfile = strdup(outfile)) == NULL) 
                                croak("strdup() returned NULL in 
Image::Rmap::newOptions() for outfile\n");
                if (colorfile) 
                        if ((RETVAL->colorfile = strdup(colorfile)) == NULL) 
                                croak("strdup() returned NULL in 
Image::Rmap::newOptions() for colorfile\n");

                RETVAL->cities = cities;
                RETVAL->gridlines = gridlines;
                RETVAL->zoom = zoom;
                RETVAL->xrot = xrot;
                RETVAL->yrot = yrot;
                RETVAL->zrot = zrot;
                RETVAL->desired_categories = des_cat;
                RETVAL->desired_continents = des_cont;
        }
        OUTPUT:
                RETVAL

MODULE = Image::Rmap            PACKAGE = Image::Rmap::Options

void
DESTROY(options)
        Image::Rmap::Options options;
        PROTOTYPE: $
        CODE:   
        {
                printf("Image::Rmap::Options::DESTROY called\n");
                if (options->mapfile != NULL)
                        safefree(options->mapfile);
                if (options->outfile != NULL)
                        safefree(options->outfile);
                if (options->colorfile != NULL)
                        safefree(options->colorfile);
        //      safefree(options);
                printf("Image::Rmap::Options::DESTROY finished\n");
        }

MODULE = Image::Rmap            PACKAGE = Image::Rmap::Options
void 
show(options)
        Image::Rmap::Options options;
        PROTOTYPE: $
        CODE:
        {
                printf("mapfile - %s\n", options->mapfile);
                printf("outfile - %s\n", options->outfile);
                printf("colorfile - %s\n", options->colorfile);
        }



MODULE = Image::Rmap            PACKAGE = Image::Rmap

void
generate(scene, options)
        Image::Rmap::Scene scene;
        Image::Rmap::Options options;
        PROTOTYPE: $$
        CODE:
        {
                generate(scene, options);
        }


Reply via email to