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 -------------------------'