[comp.lang.eiffel] C and Eiffel ?

duns1222@w203zrz.zrz.tu-berlin.de (Martin Dunschen) (06/07/91)

Hello,

We have a problem calling eiffel from C.

We typed in the example as given in "Eiffel: The Language" Version 2.2, page
221 (but we use version 2.3 level 4) and tried to create an executable 
programm by adding an appropriate (?) "main.c". Of course we got errors 
from "ld" saying, that there are undefined symbols. Okay, so we hacked in
a toy class calling this given example. Compiled with "es" everything works
fine. Now we want to use this in conjunction with eiffel classes compiled to C.
To get these C-versions of the system's classes we generated a C-package by
changing the SDF. 

Is this necessary, or is there another way to use the C verions of the 
system classes? 

We ran "identify A" in the directory containing the C-routines.
An archive was created.

But what now? When we try to link everything together with a self written main
"ld" complains about undefined symbols (eif_create, eif_rout, eif_attr, 
MakeStr), which we found in the archive-file in __eifc.o (most of them)!

To complete the confusion we add the sources of everything as a shell-archive.
Please try it and tell us, what we do wrong.

P.S: The reason we want to do this, is the interfacing from prolog to
     eiffel, e.g. create objects, call features. 
     The used prolog has a C interface.

Thank you all for your patience !!!

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	.eiffel
#	neu.e
#	test.c
#	paket/my_main.c
# This archive created: Thu Jun  6 19:48:11 1991
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting '.eiffel'" '(477 characters)'
if test -f '.eiffel'
then
	echo shar: "will not over-write existing file '.eiffel'"
else
sed 's/^X//' << \SHAR_EOF > '.eiffel'
X------------ EIFFEL SYSTEM DESCRIPTION FILE -------------------
X--   For simple uses, just replace ``root_class_name'' below
X--   by the name of the root class of your system (lower case)
XROOT: neu
XUNIVERSE: $EIFFEL/library/structures $EIFFEL/library/support
XEXTERNAL: test.o
XNO_ASSERTION_CHECK (N): ALL
XPRECONDITIONS (Y): ALL
XALL_ASSERTIONS (N): ALL
XDEBUG (N):
XTRACE (N):
XOPTIMIZE (N): ALL
XGARBAGE_COLLECTION (N)
XC_PACKAGE (N): paket
XC_EXTERNAL: test.c
XMAKE:
XVISIBLE (N): neu
SHAR_EOF
if test 477 -ne "`wc -c < '.eiffel'`"
then
	echo shar: "error transmitting '.eiffel'" '(should have been 477 characters)'
fi
fi
echo shar: "extracting 'neu.e'" '(127 characters)'
if test -f 'neu.e'
then
	echo shar: "will not over-write existing file 'neu.e'"
else
sed 's/^X//' << \SHAR_EOF > 'neu.e'
Xclass NEU
Xfeature
X	Create is
X	external test : INTEGER language "C"
X	do
X		io.putint (test ());
X	end; -- Create
Xend -- class NEU
SHAR_EOF
if test 127 -ne "`wc -c < 'neu.e'`"
then
	echo shar: "error transmitting 'neu.e'" '(should have been 127 characters)'
fi
fi
echo shar: "extracting 'test.c'" '(341 characters)'
if test -f 'test.c'
then
	echo shar: "will not over-write existing file 'test.c'"
else
sed 's/^X//' << \SHAR_EOF > 'test.c'
X#include "/cad01/Eiffel/files/_eiffel.h"
X#include <stdio.h>
Xextern OBJPTR eif_create ();
Xextern DATUM eif_rout();
Xextern int eif_attr ();
Xint test ()
X{
X  OBJPTR obj;
X  obj = eif_create("string", 10);
X  eif_rout(obj, "append", MakeStr("Hello world"));
X  printf("Size of Eiffel string is: %d\n",(int32) eif_attr (obj, "size"));
X  return 25;
X}
SHAR_EOF
if test 341 -ne "`wc -c < 'test.c'`"
then
	echo shar: "error transmitting 'test.c'" '(should have been 341 characters)'
fi
fi
echo shar: "extracting 'my_main.c'" '(22 characters)'
if test -f 'my_main.c'
then
	echo shar: "will not over-write existing file 'my_main.c'"
else
sed 's/^X//' << \SHAR_EOF > 'my_main.c'
Xmain ()
X{
X	test ();
X}
SHAR_EOF
if test 22 -ne "`wc -c < 'my_main.c'`"
then
	echo shar: "error transmitting 'my_main.c'" '(should have been 22 characters)'
fi
fi
exit 0
#	End of shell archive

murat@fir.ucsb.edu (Karaorman, Murat) (06/13/91)

In article <702@mailgzrz.tu-berlin.de> duns1222@w203zrz.zrz.tu-berlin.de (Martin Dunschen) writes:
>Hello,
>
>We have a problem calling eiffel from C.
>
>We typed in the example as given in "Eiffel: The Language" Version 2.2, page
>221 (but we use version 2.3 level 4) and tried to create an executable 
>programm by adding an appropriate (?) "main.c". Of course we got errors 

That part of the documentation IS faulty, as I remember having bumped into
about one and a half years ago

>from "ld" saying, that there are undefined symbols. Okay, so we hacked in
>a toy class calling this given example. Compiled with "es" everything works
>fine. Now we want to use this in conjunction with eiffel classes compiled to C.
>To get these C-versions of the system's classes we generated a C-package by
>changing the SDF. 
>
>Is this necessary, or is there another way to use the C verions of the 
>system classes? 
>
>We ran "identify A" in the directory containing the C-routines.
>An archive was created.
>
>But what now? When we try to link everything together with a self written main
>"ld" complains about undefined symbols (eif_create, eif_rout, eif_attr, 
>MakeStr), which we found in the archive-file in __eifc.o (most of them)!
>
>To complete the confusion we add the sources of everything as a shell-archive.
>Please try it and tell us, what we do wrong.
[... stuff deleted  for brevity ...]

What you need to do is basicly the following:

1) create a C-package archive (using the standard identify, etc. stuff)
   and make it visible under a name you choose (do VISIBLE (Y): my_name 
   during C-package generation). This should create a my_name.a file.
2) write your C program that creates eiffel objects, sends them messages
   etc., this is similiar to the sample prgm in the documentation, EXCEPT
   before doing anything you need to start-up an associated eiffel runtime
   environment by calling 
		my_name_eiffel_init();
   before using any eiffel objects. 
2.1) In this C program you shouldn't use eif_rout ( ... )  to invoke a 
   method, but instead obtain a function pointer to the method and then
   invoke the method via this pointer. You can look at the example I give.
3) compile this C program, say test.c, using
                cc -o test test.c my_name.a 
   provided that you have the correct paths, etc.
4) (hopefully) test is runnable.
5) You don't need to create the C-package again as long as your C programs
   requirements for the Eiffel environment don't change.
6) Below is how I would modify  your test.c code that follows my guidelines. 
   The lines starting with >> are my insertions,
   The lines starting with << were in your original, they need to be removed,
   The rest is unchanged (except for inserting DATUM) from your original.

==============================test.c=======================================
  #include "/cad01/Eiffel/files/_eiffel.h"
  #include <stdio.h>

>> #include " ... rename.h "
>> #include " ... Eiffel_rout.h"

  extern OBJPTR eif_create ();
  extern DATUM eif_rout();
  extern int eif_attr ();

<<  int test ()
>>  main ()
  {
    OBJPTR obj;
>>  ROUT_PTR f_ptr;

>>  my_name_eiffel_init();
 
    obj = eif_create("string",(DATUM) 10);

>>  f_ptr = eif_rout (obj, "append");
>>  (* f_ptr)(obj, MakeStr("Hello world"));
 
<<  eif_rout(obj, "append", MakeStr("Hello world"));
    printf("Size of Eiffel string is: %d\n",(int32) eif_attr (obj, "size"));
    return 25;
  }

=================================end====================================


I hope this helps. Let me know if anything goes wrong. It has been a while
now, but I know that this stuff should eventually work.

good luck,

-----------------------------------------------------------------------------.
|        Two men say they're Jesus...					      |
|        One of them must be wrong.					      |
|                     -Dire Straits "Industrial Disease" from Love Over Gold  |

murat@fir.ucsb.edu (Karaorman, Murat) (06/19/91)

In my previous posting, <12051@hub.ucsb.edu>, about calling Eiffel routines 
from C, I just noticed that I have overlooked an important (yet obvious) 
mistake that was in the original documentation. I had stated it in words:
 
>2.1) In this C program you shouldn't use eif_rout ( ... )  to invoke a 
>   method, but instead obtain a function pointer to the method and then
>   invoke the method via this pointer. You can look at the example I give.

but forgotten to include in the example.

Here the type of eif_rout() needs to be a function pointer, namely ROUT_PTR,
as opposed to the type DATUM in the original article, therefore the 
example program should read:

==============================test.c=======================================
  #include "/cad01/Eiffel/files/_eiffel.h"
  #include <stdio.h>

>> #include " ... rename.h "
>> #include " ... Eiffel_rout.h"

  extern OBJPTR eif_create ();
<<  extern DATUM    eif_rout();
>>  extern ROUT_PTR eif_rout ();
  extern int eif_attr ();

<<  int test ()
>>  main ()
  {
    OBJPTR obj;
>>  ROUT_PTR f_ptr;

>>  my_name_eiffel_init();
 
    obj = eif_create("string",(DATUM) 10);

>>  f_ptr = eif_rout (obj, "append");
>>  (* f_ptr)(obj, MakeStr("Hello world"));
 
<<  eif_rout(obj, "append", MakeStr("Hello world"));
    printf("Size of Eiffel string is: %d\n",(int32) eif_attr (obj, "size"));
    return 25;
  }

=================================end====================================

   The lines starting with >> are my insertions,
   The lines starting with << were in your original, they need to be removed,
   The rest is unchanged (except for inserting DATUM) from your original.
 
Sorry for any inconvenience this may have caused.

Murat Karaorman,

>
>I hope this helps. Let me know if anything goes wrong. It has been a while
>now, but I know that this stuff should eventually work.
>
>good luck,
>
>-----------------------------------------------------------------------------.
>|        Two men say they're Jesus...					      |
>|        One of them must be wrong.					      |
>|                     -Dire Straits "Industrial Disease" from Love Over Gold  |


------------ Two men say they're Jesus...    ----.
|             One of them must be wrong.	  |
|                             -Dire Straits       |
`----  murat@cs.ucsb.edu -------------------------'