[m-dev.] Help with C Interface

Gustavo A. Ospina gos at info.ucl.ac.be
Wed Mar 14 04:15:41 AEDT 2001


Hello,

I'm doing a little experiment with the C interface. The main program is
written in C and it calls Mercury code.

I use a container structure (binary tree) and a record structure
(person), both of them implemented in Mercury.

The main program is a text user interface which uses a menu of options
(add a person to the tree, delete a person, prints all the persons,
etc).

Here a brief detail of the main algorithm in C:

/* Mercury types tree and person are bound to type MR_Word in C */
typedef MR_Word m_tree;
typedef MR_Word m_person;

/* Functions:
c_init_tree();			/* Exported by Mercury in module tree.m */
c_add_tree(Person, Tree);	/* Exported by Mercury in module tree.m */
c_make_person(Id, Name);	/* Exported by Mercury in module person.m */

main()
{    m_tree tr;
     m_person pe;
     int id;
     char * name;
     int opt

     tr = c_init_tree();

     while(<exit option not selected>){
          opt = <read option from menu>;
          switch(opt){
          case 1: /* Addition */
               <read id>;
               name = (char *) malloc (MAX_NAME * sizeof(char));
               <read name with gets()>;
               pe = c_make_person(id, name);
               tr = c_add_arbin(pe, tr);
               free(name);
               break;
          /* Another cases */
          }
     }
     return;
}

There is a problem with the addition case. The string field in parameter
'pe', when a second person is added, is changed for all the persons
contained in the tree. For exemple, if the first person read is (10,
Pelé) and the second person read is (14, Cruyff), when I print all the
persons I get:

Person 10 : Cruyff
Person 14 : Cruyff

Pointer problem? yes... I've tried using a pointer to the person
structure (variable pe) and the result is the same. I must recall that
fonction c_make_person is implemented in Mercury and exported, like
this:

:- func make_person(int, string) = person.

make_person(Id, Name) = person(Id, Name).

:- pragma export(make_person(in, in) = (out), "c_make_person").

I've found two alternatives: I can write the main algorithm in a
recursive way, instead of an iterative one. I can also implement the
record structure directly in C and make the "paste" to the Mercury tree
using the importation interface and the special type 'c_pointer'. The
first solution is not efficient, the second breaks the original design.

I would like to know how could I copy the information of a person record
(in the "adding" case of the main cycle) to avoid this side effect. I
think I do probably something which is conflicting with the internal
memory management in Mercury, but I don't know.

I'll be able to send you the original code. Thank you for your help.
Best regards.

+ Gustavo +
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list