fcaggian@kepler.com (Frank Caggiano) (10/18/90)
I have been trying to access an Eiffel object from a C routine and am having no luck. What I need to do is access a fixed list of intergers from the C routine. I have tried all the ways I can think of using the routines shown on pages 220-221 of Eiffel the language. They don't specifically show the object being passed in however so is this possible? Also while I've ben going through this I thought that if I created the object in C passed it back to eiffel and then passed it back to C maybe it would work then. GHowever when I went to write the C call to eif_create I bummped up afgainst the fact that FIXD_LIST is a constrained type. How do you create a constrained type in C ? All I could comme up with was: eif_create("fixed_list[integer]",some-number) but seems a bit far fechted. I haven't had time to try it out. Anyone have any ideas? Below is an example of code for my first problem: The Eiffel part: class CEIF feature Create is external foo: language "C" local x: FIXED_LIST[INTEGER] do x.Create(3); x.put_i_th(1,1); x.put_i_th(2,2); x.put_i_th(3,3); x.start; io.putint(x.item); io.new_line; x.forth; io.putint(x.item); io.new_line; x.forth; io.putint(x.item); io.new_line; x.start; foo(x); end; end; The C part: #include "/usr/local/Eiffel/files/_eiffel.h" foo(x) OBJPTR x; { int i; extern int eif_err; for (i = 1; i <= 3; i++) { printf("i = %d (%d) {%d} [%d]\n",i,eif_err,eif_attr(x,"count"), eif_attr(x, "item")); eif_rout(x,"forth"); } } what prints out (from the C part): i = 1 (-1) [0] [0] i = 2 (-1) [0] [0] i = 3 (-1) [0] [0] The printout in Eiffel is ok. -- Frank Caggiano INTERNET: fcaggian@kepler.com Kepler Financial Management, Ltd. UUCP: ..!uunet!kepler1!fcaggian 100 North Country Rd. fax: (516) 751-8678 Sekauket, NY 11733 voice: (516) 689-6300
tarvydas@turing.toronto.edu (Paul Tarvydas) (10/18/90)
There's a problem with your C code and with documentation: 1) My copy of 'Eiffel: The Language' incorrectly documents "eif_rout". It returns a *pointer* to a routine. [Also, the names in the C string must be entirely lower case and 25 characters or less.] So, after calling "eif_rout", you still have to call the routine, eg. (*(eif_rout (obj, "feat"))) (obj); or, more humanely put (and, more efficiently, if you're going to make the call more than once): ptr = eif_rout (obj, "feat"); ... (*ptr) (obj); [Remember that you have to supply the "Current" Eiffel object as the first arg to an Eiffel routine.] 2) Your C code is wrong because "item" is a routine, not an attribute (maybe that's why you got the -1 eif_err's). So, here's your C code: ============================ #include <stdio.h> #include "/home/Eiffel/files/_eiffel.h" foo(x) OBJPTR x; { int i; extern int eif_err; extern ROUT_PTR eif_rout (); ROUT_PTR item, forth; item = eif_rout (x, "item"); if (item == NULL) { fprintf (stderr, "can't find 'item'\n"); exit (1); } forth = eif_rout (x, "forth"); if (item == NULL) { fprintf (stderr, "can't find 'forth'\n"); exit (1); } for (i = 1; i <= 3; i++) { printf("i = %d (%d) {%d} [%d]\n", i, eif_err, eif_attr (x, "count"), (*item) (x)); (*forth) (x); } } ============================== And here's the output: 1 2 3 i = 1 (0) {3} [1] i = 2 (0) {3} [2] i = 3 (0) {3} [3] As to your question about C-creating instances of generic types, why not write a new class, say "fixed_list_of_integer", then Create it? eg. class FIXED_LIST_OF_INTGER export repeat FIXED_LIST inherit FIXED_LIST [INTEGER] rename Create as flCreate feature Create (n : INTEGER) is do flCreate (n); end; end; Paul Tarvydas tarvydas@tsctrl.uucp TS Controls 5 Bowness Crt. Etobicoke, Ontario, Canada M9B 5Z8 tel. (416)-234-0889, fax. (416)-234-9193
nosmo@eiffel.UUCP (Vince Kraemer) (10/19/90)
If you have been having trouble with the issue of using Eiffel objects in C code and have access to a fairly good archive of comp.lang.eiffel, I would suggest (re)reading message <391@eiffel.UUCP>, which covers the subject and agrees with the implementation of 2.2 (and 2.3). If you don't, I can post it again or mail it to you (depending on the demand). Another item covered in the cited article is the use of class MEMORY to deal with the disposal of externally allocated resources, when an object is garbage collected. Well, I hate to say it, but I believed the documentation in the class and the semantics that were discussed when this feature was being designed. In testing this feature, I discovered that it works, if you respect the following caveats, which are not documented: 1. The dispose will only work in DIRECT descendants of MEMORY only. 2. The dispose feature is only called when the routine MEMORY.full_collect is called (not MEMORY.collect is called or when the collection is triggered automatically). This does limit the applicability of using dispose or of automatic memory management considerably. There is a caveat, for those who can still make good use of dispose, to apply when writing dispose routines: DO NOT apply remote notation (dots) to attributes. There is no order implied in the collection of garbage. This means that it is possible that an attribute of an object has been collected before it client. Trying to dereference the collected object will raise an exception. I wish to apologize to all those who may have been mislead by my previous posting. I have learned my leason though: test then post. The following shar file has a system to illustrate the use of dispose (correctly). Vince Kraemer ISE Tech. Support (technical correspondence to: eiffel@eiffel.com) ----------------------------- sh-archive ------------------------------- # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by geneve!nosmo on Thu Oct 18 17:12:48 PDT 1990 # Contents: a.e driver.e .eiffel echo x - a.e sed 's/^@//' > "a.e" <<'@//E*O*F a.e//' --|--------------------------------------------------------------- --| Copyright (C) Interactive Software Engineering, Inc. -- --| 270 Storke Road, Suite 7 Goleta, California 93117 -- --| (805) 685-1006 -- --| All rights reserved. Duplication or distribution prohibited -- --|--------------------------------------------------------------- --| Author: Vincent Kraemer @ Interactive Software Engineering --| Created: Thu Oct 18 09:26:43 1990 class A export inherit MEMORY redefine dispose; feature a1, a2, a3, a4: integer; dispose is do -- The use of io will be okay since it is shared. -- all others you must be careful about. io.putstring ("Disposing of an A."); io.new_line; end; end -- class A @//E*O*F a.e// chmod u=rw,g=rw,o=r a.e echo x - driver.e sed 's/^@//' > "driver.e" <<'@//E*O*F driver.e//' class DRIVER export inherit MEMORY feature hold: ARRAY [A]; Create is local an_a: A; ol, il: integer; do io.putstring ("Now using manual storage control."); io.new_line; collection_off; from ol := 0 until ol = 200 loop io.putstring ("second test: "); io.putint (ol); io.new_line; hold.create (0, 100000); from il := 0; until il > 100000 loop an_a.create; hold.put (an_a, il); il := il + 1; end; ol := ol + 1; hold.forget; full_collect; collection_off; end; end; end -- class DRIVER @//E*O*F driver.e// chmod u=rw,g=rw,o=r driver.e echo x - .eiffel sed 's/^@//' > ".eiffel" <<'@//E*O*F .eiffel//' ------------ EIFFEL SYSTEM DESCRIPTION FILE ------------------- -- For simple uses, just replace ``root_class_name'' below -- by the name of the root class of your system (lower case) ROOT: driver UNIVERSE: /usr/local/Eiffel/library/support EXTERNAL: NO_ASSERTION_CHECK (N): PRECONDITIONS (Y): ALL ALL_ASSERTIONS (N): DEBUG (N): TRACE (N): OPTIMIZE (N): GARBAGE_COLLECTION (y) C_PACKAGE (N): C_EXTERNAL: MAKE: VISIBLE (N): ---------------------------------------------------------------- @//E*O*F .eiffel// chmod u=rw,g=rw,o=r .eiffel exit 0