Hello,
I am trying to use openoffice myThes code. This code is written in C and now I need that code in python.
I have used swig tool to convert the c code in python. The python code has been produced. but problem is the c main function takes a list of 3 files as char pointer to pointer(char * *). And I could not pass the dictionary pointer in the main function from python shell.
Here is the code

#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <stdio.h>

#include "mythes.hxx"
#include "mythes.cxx"

extern char * mystrdup(const char * s);

using namespace std;

int 
main(int argc, char** argv)
{
    char * af;
    char * df;
    char * wtc;
    FILE* wtclst;

  /* first parse the command line options */
  /* arg1 - index file, arg2 thesaurus data file, arg3 - file of words to check */

  if (argv[1]) { 
	//printf(argv); 
       af = mystrdup(argv[1]);
       fprintf(stderr,"arg[1]\n"); 	
  } else {
    fprintf(stderr,"arg[1],correct syntax is:\n"); 
    fprintf(stderr,"example index_file thesaurus_file file_of_words_to_check\n");
    exit(1);
  }
  if (argv[2]) {
       df = mystrdup(argv[2]);
       fprintf(stderr,"arg[2]\n"); 
  } else {
    fprintf(stderr,"arg[2],correct syntax is:\n"); 
    fprintf(stderr,"example index_file thesaurus_file file_of_words_to_check\n");
    exit(1);
  }
  if (argv[3]) {
       wtc = mystrdup(argv[3]);
       fprintf(stderr,"arg[2]\n");
  } else {
    fprintf(stderr,"arg[3],correct syntax is:\n"); 
    fprintf(stderr,"example index_file thesaurus_file file_of_words_to_check\n");
    exit(1);
  }

  
  /* open the words to check list */
  wtclst = fopen(wtc,"r");
  if (!wtclst) {
    fprintf(stderr,"Error - could not open file of words to check\n");
    exit(1);
  }

    // open a new thesaurus object
    MyThes * pMT= new MyThes(af,df);

    // get the encoding used for the thesaurus data
    char * encoding = pMT->get_th_encoding();
    fprintf(stdout,"Thesaurus uses encoding %s\n\n",encoding);
    
    int k;
    char buf[101];
    mentry * pmean;

    while(fgets(buf,100,wtclst)) {
      k = strlen(buf);
      *(buf + k - 1) = '\0';
      int len = strlen(buf);
      int count = pMT->Lookup(buf,len,&pmean);
      // don't change value of pmean
      // or count since needed for CleanUpAfterLookup routine
      mentry* pm = pmean;
      if (count) {
        fprintf(stdout,"%s has %d meanings\n",buf,count);
	for (int  i=0; i < count; i++) {
          fprintf(stdout,"   meaning %d: %s\n",i,pm->defn);
          for (int j=0; j < pm->count; j++) {
	    fprintf(stdout,"       %s\n",pm->psyns[j]);
          }
          fprintf(stdout,"\n");
          pm++;
	}
        fprintf(stdout,"\n\n");
        // now clean up all allocated memory 
        pMT->CleanUpAfterLookup(&pmean,count);
      } else {
        fprintf(stdout,"\"%s\" is not in thesaurus!\n",buf);
      }
    }

    delete pMT;
    fclose(wtclst);
    free(wtc);
    free(df);
    free(af);

    return 0;
}

my interface file is :

/* example.i */
 %module example
 %{
 /* Put header files here or function declarations like below */

int main(int argc, char** argv);
 %}
int main(int argc, char** argv);

the command I ran from terminal :

$ swig -python -c++ example.i
$ g++ -I/usr/include/python2.5 -c example.cxx example_wrap.cxx
$ ld -shared example.o example_wrap.o -o _ /usr/lib/libg++.so.2.7.2 /usr/lib/libstdc++.so.6
$ python
>>> import example
>>> example.main(3, )
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: in method 'main', argument 2 of type 'char **'

Normally when I run the c file , it will find the synonyms of the word specified in checkme.lst.

$ g++ example.cxx -o example
$ ./example th_en_US_new.idx th_en_US_new.dat checkme.lst
Thesaurus uses encoding ISO8859-1

buck-toothed has 1 meanings
meaning 0: (adj) toothed
toothed

Can anyone give me any hints ?

Thanks ,
monjuri

Dani AI

Generated

Quick summary and the likely cause (what ran into)
Passing a raw C char ** back-and-forth between Python and a SWIG wrapper is fragile because of ownership and lifetime rules. The SWIG wrappers already know how to convert a Python sequence of strings into char ** for you — constructing a char ** in C and returning it to Python (the convert approach) easily leads to dangling pointers or memory corruption. The symptom you saw ("File 'checkme.lst' ... SyntaxError" followed by a segfault) is consistent with memory corruption or a bad pointer being interpreted by the interpreter/runtime.

Quick, low-effort fix
Call the wrapped main with a Python list (and make argc match the list length). Example:

argv = ["program", "th_en_US_new.idx", "th_en_US_new.dat", "checkme.lst"]
example.main(len(argv), argv)

SWIG will translate that Python list into char ** for the C function. Make sure argc equals len(argv) (include an argv[0] placeholder if the C code expects it).

Safer, more robust solution
Do not export the C main. Instead add a small C wrapper with a distinct name that accepts three const char * arguments (index, data, words) and returns results in a Python-friendly form (an int status or a list/dict of results). Example signature:

/* expose this to Python via SWIG */
int run_thesaurus(const char *index_file, const char *data_file, const char *words_file);

Call example.run_thesaurus(...) from Python. This avoids juggling char ** lifetimes and prevents accidental frees of Python-owned buffers.

Troubleshooting notes

  • If a quick-list call still crashes, check for frees of pointers that were not malloc'd (freeing Python-owned memory will crash).
  • Run the C code standalone (same arguments) to confirm its logic is solid.
  • Use tools like valgrind to catch invalid reads/frees.
  • ’s idea of keeping the heavy logic out of main or invoking the compiled program from Python (subprocess) are pragmatic fallbacks while building a proper wrapper.

Recommended Answers

All 5 Replies

Temp file and passing the name is maybe easy solution. Feels maybe clumsy, but should work.

Other thing maybe would to define new function in your C++ code using Python interface specification. Then there is the solution of using Shedskin for a small python program which uses dict as parameter and and paste function main content from abouve code without the argv part.

Then you could look those mythes headers and maybe create interface to functions directly. Then do the loop in the main with python.

Unfortunately I have minimal experience with Python - C++ interface. Maybe somebody who has actually used it more has good ideas.

How about calling the C program and capturing output?
For example: A Command class to run shell commands.

Or you can separate the logic of the function out of the main to function with maybe fixed two file name parameters and one char* for string. Then you can prepare interface for that function.

Document Simple pointers
5.3.3 Derived types, structs, and classes has example:

%module fileio
FILE *fopen(char *, char *);
int fclose(FILE *);
unsigned fread(void *ptr, unsigned size, unsigned nobj, FILE *);
unsigned fwrite(void *ptr, unsigned size, unsigned nobj, FILE *);
void *malloc(int nbytes);
void free(void *);
# Copy a file 
def filecopy(source,target):
	f1 = fopen(source,"r")
	f2 = fopen(target,"w")
	buffer = malloc(8192)
	nbytes = fread(buffer,8192,1,f1)
	while (nbytes > 0):
		fwrite(buffer,8192,1,f2)
		nbytes = fread(buffer,8192,1,f1)
	free(buffer)

Hello tonyjv,
Many thanks for your suggestions.
I have written the interface file so that it can externally take the 3 files and return their pointer to pointer.
The interface file is:

/* example.i */
 %module example
 %{
 /* Put header files here or function declarations like below */

int main(int argc, char** argv);
%}
%inline %{
char** convert (char* a, char* b, char* c){
	char** array;
	array = (char**) malloc(3 * sizeof(char *));
	array[0] = a;
	array[1] = b;
	array[2] = c;
	return array;

}%}

int main(int argc, char** argv);
char** convert (char* a, char* b, char* c);

Now it can find the file. Problem is - when I run it from python interpreter, it cannot process anything that violates it's own syntex.
Among the three files there is a file named ""th_en_US_new.dat". And while manipulating the file it shown the following error in terminal.
$ python
>>> import example
>>> fg=example.convert("th_en_US_new.idx","th_en_US_new.dat","checkme.lst")
>>> example.main(3,fg)
File "checkme.lst", line 2
'hood|1
^
SyntaxError: EOL while scanning single-quoted string
Segmentation fault
Here it cannot process the single coding. but this thing didn't raise any problem while running the c files.
I have ran these commands from a python script and got the same problem.
Can you give any idea how this problem can be solved?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.