[Tutor] Extending Python with C++ by using SWIG

Marcus Konermann m_konermann@gmx.de
Sun, 14 Oct 2001 20:15:59 +0200


This is a multi-part message in MIME format.
--------------090406070505010807060407
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 8bit

Hallo !

Im developing a project excisting of a Tkinter User Interface and C++ 
and some Python Code. So the first Step i want to do is to extend the 
Tkinter User Interface with the C++ Code by using SWIG and for me its 
the first time working with SWIG (but by the way i think its for me the 
fastest way to integrate the C++ Code in Python). Im working under 
win2000 with pywin and im using the VC++ 6.0 Compiler. I hope that i 
installed the SWIG Wrapper correct under VC++ 6.0, but after building 
the project the following mistakes are produced from the Compiler:

SWIG
Generating wrappers for Python
..\basisfile.i : Line 10. Warning.  Use of C++ Reference detected.  Use 
the -c++ option.
Kompilierung luft...
basisfile.cpp
basisfile.obj : error LNK2001:
Nichtaufgeloestes externes Symbol "public: 
__thiscallstring::~string(void)"(??1string@@QAE@XZ)
basisfile.obj : error LNK2001:
Nichtaufgeloestes externes Symbol "public: __thiscall 
string::string(void)" (??0string@@QAE@XZ)
basisfile.obj : error LNK2001:
Nichtaufgeloestes externes Symbol "public: void __thiscall 
string::clean(void)" (?clean@string@@QAEXXZ)
...

Perhaps theres a problem with classes in SWIG and i have to write 
additional Information for the SWIG Wrapper in the basisfile.i  File.
So, it would be very good for me if anyone already worked with SWIG and 
can help me.

Thanks a lot
Marcus


--------------090406070505010807060407
Content-Type: text/plain;
 name="basisfile.cpp"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="basisfile.cpp"

#include "basisfile.h"

filetext::filetext () {
  tlln = 0;
  tfln = 0;
  variable_pointer = NULL;
  next = NULL;
}

filetext::~filetext () {
  clean ();
}


void filetext::clean () {
  clean (this);
}

void filetext::clean (struct filetext *ft) {
  if (ft) {
    if (ft->next) { 
      clean (ft->next);
      ft->next = NULL;
    }
    variable_pointer = NULL;
    text.clean ();
    parameter_text.clean ();
  }
}

basisfile::basisfile () {
  filename = NULL;
  text = NULL;
}

basisfile::basisfile (struct string &fn) {
  filename = new struct string;
  filename->copy (fn);
  text = NULL;
}

basisfile::basisfile (char *fn) {
  init (fn);
}

basisfile::~basisfile () {
  clean ();
}

void basisfile::init (char *fn) {
  filename = new struct string;
  filename->copy (fn);
  text = NULL;
}
  

void basisfile::clean () {
  if (filename) {
    delete filename;
    filename = NULL;
  }
  if (text) {
    delete text;
    text = NULL;
  }
}

int basisfile::readfile () {
  if (!filename->size) {
    printf ("basisfile::readfile:\n No filename to read specified.\n");
    return 1;
  }
  
  /* initialize text-pointer */
  text = new struct filetext;
    
  /* Copy complete input file to text */
  text->tfln = 1;
  if ((text->tlln = text->text.filereadc (*filename, '\n')) < 0) {
    printf ("basisfile::readfile ():\n ");
    strprint (*filename, "Error while reading file `", "'.\n");
    return 1;
  }
  
  return 0;
}


int basisfile::writefile (string &otherfilename, char *mode) {
  struct filetext *help = this->text;
    
  if ( (*mode != 'a') && (*mode != 'w') ) {
    printf ("basisfile::writefile:\n Invalid mode %s ", mode);
    strprint (otherfilename, "for writing to file `", "'.\n");
    return 1;
  }
  
  FILE *out = otherfilename.fileopen (mode);

  if (out)
    while (help != NULL) {
      if (help->text.size)
	help->text.filewrite (out);
      if (help->parameter_text.size)
	help->parameter_text.filewrite (out);
      help = help->next;
    }
  else {
    strprint (otherfilename, "basisfile::writefile:\n Unable to open file `",
	      "'");
    printf (" with mode %s.\n", mode);
    return 2;
  }

  while (help != NULL) {
    if (help->text.size)
      help->text.filewrite (otherfilename, "a");
    if (help->parameter_text.size)
      help->parameter_text.filewrite (otherfilename, "a");
    help = help->next;
  }
  
  return 0;
}


int basisfile::writefile (char *mode) {
  struct filetext *help = this->text;
    
  if ( (*mode != 'a') && (*mode != 'w') ) {
    printf ("basisfile::writefile:\n Invalid mode %s ", mode);
    strprint (*filename, "for writing to file `", "'.\n");
    return 1;
  }
  
  FILE *out = filename->fileopen (mode);

  if (out) {
    while (help != NULL) {
      if (help->text.size)
	help->text.filewrite (out);
      if (help->parameter_text.size)
	help->parameter_text.filewrite (out);
      help = help->next;
    }
    fclose (out);
  }
  else {
    strprint (*filename, "basisfile::writefile:\n Unable to open file `", "'");
    printf (" with mode %s.\n", mode);
    return 2;
  }

//    while (help != NULL) {
//      if (help->text.size)
//        help->text.filewrite (*filename, "a");
//      if (help->parameter_text.size)
//        help->parameter_text.filewrite (*filename, "a");
//      help = help->next;
//    }

  return 0;
}


int basisfile::build (struct variablelist *variable) {
  struct filetext *help;
  int splitswitch;

  /* Look for specified variable */
  while (variable) {
    help = this->text;
    /* search all parts of basisfile (except in parameter-text-parts) */
    while (help) {
      /* search in text */
      if (variable->linenumber <= help->tlln) {
	/* split text */
	if ( split (&help, variable) ) {
	  printf ("Error while splitting basisfile structure.\n");
	  return 1;
	}
	else
	  /* parameter found */
	  help = NULL;
      }
      else {
	/* nothing found */
	help = help->next;
      }
    }
    /* found parameter? */
    if (!variable->text) {
      printf ("Couldn't find parameter number %d.\n", variable->number);
      printf ("Probably line number %d exceeds number of lines of file.\n",
	      variable->linenumber);
      return 2;
    }
    /* look at next one */
    variable = variable->next;
  }
  return 0;
}


int basisfile::split (struct filetext **text, struct variablelist *variable, 
		      int separators) {
  int line = (*text)->tfln; 
  int linepos = 0, prepos = 0, pastpos;
  int original_size = (*text)->text.size;
  int original_tlln = (*text)->tlln;
  string help, dummy;
  int next_line_offset;
  struct filetext *hft = NULL;

  /* check text */
  if (!text || !(*text)) {
    printf ("basisfile::split:\n Empty filetext structure.  Aborting.\n");
    return 100;
  }

  /* check linenumber and position */
  if (variable->linenumber < 1) {
    printf ("basisfile::split:\n Invalid linenumber %d.\n",
	    variable->linenumber);
    return 99;
  }
  if (variable->position < 0) {
    printf ("basisfile::split:\n Invalid position %d.\n",
	    variable->position);
    return 99;
  }

  /* find right line */
  while (line < variable->linenumber) {
    linepos += (*text)->text.string_complement_span("\n", linepos) + 1;
    line++;
  }
   
  next_line_offset = (*text)->text.string_complement_span("\n", linepos) + 1;
  /* if "\n" was not found, next_line_offset is position of "\0".
     Since this character is not meant to be copied to help, we must
     decrease next_line_offset by 1 in this case. */
  if (next_line_offset+linepos == (*text)->text.size)
    help.ncopy ((*text)->text, next_line_offset-1, linepos);
  else
    help.ncopy ((*text)->text, next_line_offset, linepos);
  
  /* find beginning position of parameter-text in line */
  while (separators < variable->position) { 
    /* if not found */
    if (!(help.string_string(dummy, variable->preseparator, prepos+1))) {
      /* Does line in question continue with next struct? */
      if ( ((*text)->next) && ((*text)->next->tfln == line) )
	return (split ( &((*text)->next), variable, separators));
      else {
	printf("Problem in line no. %d:\n", line);
	printf(" Can not find more than %d", separators);
	strprint (variable->preseparator, " preseparators `", "'.\n");
	printf(" Should have found %d.\n", variable->position);
	strprint (help, "Text of the line under consideration:\n \"", "\"\n");
	return 1;
      }
    } 
    prepos = help.size - dummy.size;
    separators++;
  }

  /* if no separators were meant to be found, dummy would not contain
     the string continuing with guessed variable-text start: dummy
     would be empty. */
  if (!separators)
    dummy.copy (help);

  /* find ending position of parameter-text in line */
  if (!variable->pastseparator.size) {
    printf("Problem with specification of variable no. %d:\n", 
	   variable->number);
    printf(" pastseparatpor is empty.\n");
    return 2;
  }
  else
    if (!(help.string_string(dummy, variable->pastseparator, 
			     help.size-dummy.size 
			     + variable->preseparator.size - 1))) {
      printf("Problem in line no. %d:\n", line);
      printf(" Can not find");
      strprint (variable->pastseparator, " pastseparator `", "' after ");
      printf ("%d. ", separators);
      strprint(variable->preseparator, "presaparator `", "'.\n");
      strprint (help, "Text of the line under consideration:\n \"", "\"\n");
      return 3;
    } 

  pastpos = linepos + help.size - dummy.size;

  /* set adequat positions of beginning of parameter_text */
  prepos += linepos + variable->preseparator.size - 1;

  /* save whole text */
  dummy.copy ((*text)->text);
  /* copy non-parameter-text to text */
  (*text)->text.ncopy (dummy, prepos);
  /* breaking line no. $line means, that text last line number is $line now. */
  (*text)->tlln = line;

  /* Are we dealing with a line already splitted into text and
     paramter_text?  Then save parameter_text and variable_pointer and
     take care of the variable-pointer to this old parameter_text. */
  if ((*text)->parameter_text.size) {
    /* create new basisfile-node */
    hft = new struct filetext;
    /* save parameter_text there. */
    hft->parameter_text.copy ((*text)->parameter_text);
    /* save variable_pointer, too */
    hft->variable_pointer = (*text)->variable_pointer;
    /* redirect variablelist-pointer to new location of old parameter_text. */
    hft->variable_pointer->text = hft;
  }
  /* is some original text left behind new parameter_text?  Save it!  */
  if (pastpos < original_size) {
    /* create new basisfile-node, if not done already */
    if (!hft)
      hft = new struct filetext;
    /* save rest of the text in new node, too */
    hft->text.ncopy (dummy, original_size-pastpos-1, pastpos);
  }

  /* copy parameter-text to parameter_text */
  (*text)->parameter_text.ncopy (dummy, pastpos-prepos, prepos);
  /* link pointer of variable to according parameter_text and backlink
     pointer of *text to that same variable pointer. */
  variable->text = (*text);
  (*text)->variable_pointer = variable;
  
  /* set adequat line numbers for new node and link it to the
     structure, if new node exists. */
  if (hft) {
    /* text last line number is last line number of original text. */
    hft->tlln = original_tlln;
    /* if parameter_text does not include '\n' of original line, new
       text first line number is just the number of the breaked line
       ($line).  Otherwise new tfln is number of next line. */
    if ((*text)->parameter_text.string_character ('\n'))
      hft->tfln = line+1;
    else
      hft->tfln = line;
    /* link new node to structure.  aehm?? Take care of pointer of variable
       struct pointing to text->next. */
    hft->next = (*text)->next;
    //hbf->next->variable_pointer->text = &hbf;
    (*text)->next = hft;
  }
  return 0;
}

int vl2pt (struct variablelist *vl) {
  while (vl) {
    if (vl->text) {
      if (vl->text->parameter_text.copy (vl->x_now)) {
	printf ("vl2pt:\n ");
	printf ("Error while copying x_now to paramter text.\n");
	return 1;
      }
    }
    else {
      printf ("vl2pt:\n ");
      printf ("Cannot find paramter text for variable no. %d.\n", 
	      vl->number);
      return 2;
    }
    vl = vl->next;
  }
  return 0;
}

void print (struct filetext *ft) {
  while (ft) {
    printf ("tfln = %d\ttlln = %d\n", ft->tfln, ft->tlln);
    printf ("variablen_pointer->nummer = ");
    if (ft->variable_pointer)
      printf("%d\n", ft->variable_pointer->number); 
    else
      printf("\n");
    strprint (ft->text, "text:\n `", "'\n");
    strprint (ft->parameter_text, "parameter_text: `", "'\n");
    ft = ft->next;
  }
}

--------------090406070505010807060407
Content-Type: text/plain;
 name="basisfile.h"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="basisfile.h"

#ifndef BASISFILE_H
#define BASISFILE_H

#include "safe_string.h"
#include "variable.h"

struct filetext {
  filetext ();
  ~filetext ();

  void clean (struct filetext *ft);
  void clean ();

  struct string text;
  struct string parameter_text;
  /* text first line number */ 
  int tfln;
  /* text last line number */
  int tlln;
  /* pointer to the variable-struct, which points to this
     text-struct. */
  struct variablelist *variable_pointer;
  struct filetext *next;
};

struct basisfile {
  basisfile ();
  basisfile (struct string &fn);
  basisfile (char *fn);
  ~basisfile ();

  void init (char *fn);
  void clean ();
  
  struct filetext *text;
  struct string *filename;

  int readfile ();
  /* write this.text and this.parameter_text to file 'filename'.
     writefile walks through from this to last element of next-pointer
     and writes first text and then parameter_text to the file.  The
     file is opened once in mode 'mode'.  Values of mode are meant to
     be "w"- or "a"-modes according to the fopen()-function. */
  int writefile (struct string &filename, char *mode = "w");
  int writefile (char *mode = "w");
  int build (struct variablelist *variable);
  /* searches parameter_text specified in 'variable' in text of
     'text'.  If found, the text of 'text' is split into 'text' and
     'parameter_text' and in case some text of the line is left, a new
     node is inserted into 'text'.  In case of **text contains a
     splitted line, split will call itself recursively in order to
     search the whole line.  The text-pointer of *variable is set to
     the node of **text containing the parametertext belonging to
     variable.

     How is parameter_text searched for?  It is searched for the line
     variable->linenumber.  variable->preseparator and
     variable->pastseparator gives the text left and right from the
     searched parameter_text.  variable->position gives the number of
     preseparator sets which must be found before parameter_text.  If
     variable->position is 0, variable->preseparator is ignored and it
     is assumed, that the parameter_text starts at the beginning of
     the line.  If enough preseparators are found, the pastseparator
     will be searched for.  An empty pastseparator will lead to an
     error, if the file is continuing after the parameter_text.  A
     pastseparator not found, too.

     Return value is 0, if everything is fine, > 0 if an error occured.
  */
  int split (struct filetext **text, struct variablelist *variable, 
	     int separators = 0);
};

/* Copys x_now of variables to their parameter_texts */
int vl2pt (struct variablelist *vl);
void print (struct filetext *ft);
#endif

--------------090406070505010807060407
Content-Type: text/plain;
 name="basisfile.i"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="basisfile.i"

%module mybasisfile
%{
#include "basisfile.h"
%}
extern filetext ();
extern void clean ();
extern basisfile ();
extern void init (char *fn);
extern int readfile ();
extern int writefile (string &otherfilename, char *mode);
extern int build (struct variablelist *variable);
extern int split (struct filetext **text, struct variablelist *variable,int separators);
extern int vl2pt (struct variablelist *vl); 
extern void print (struct filetext *ft);
--------------090406070505010807060407--