Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!rutgers!apple!sun-barr!cs.utexas.edu!uunet!mcvax!kth!draken!tut!tukki!sakkinen From: sakkinen@tukki.jyu.fi (Markku Sakkinen) Newsgroups: comp.lang.eiffel Subject: Re: Eiffel type system <133@eiffel.UUCP> Summary: Errors in C interface description pointed out Keywords: C interface, composite objects Message-ID: <873@tukki.jyu.fi> Date: 12 Jun 89 06:10:16 GMT References: <154@eiffel.UUCP> Reply-To: markku@jytko.jyu.fi (Markku Sakkinen) sakkinen@finjyu.bitnet (alternative) Organization: University of Jyvaskyla, Finland Lines: 66 The article referred to was entitled "EIFFEL TYPES" (by Bertrand Meyer). Note: this submission talks _only_ about the Eiffel-C interface (one short section of the full paper length article). In section 7 (Argument passing), Meyer writes: > For arguments to external routines, the rule cannot be > as systematic; they must of necessity be adapted to the > target language. Current C, for example, does not support > passing of structures or arrays as arguments; only pointers > to such elements may be passed. (ANSI C may be more liberal, > but has yet shown little relevance to the real world of C > programming.) So for C all arguments, whether expanded or > not, are normally passed by reference. It is the > responsibility of the target C routine to copy any structure > or array if needed. An exception is made, however, for > arguments of basic types (integer, real, boolean, character > and the new type ``long real'' described below), which are > passed by value for compatibility with tradition. > It must be a weird and antiquated C compiler indeed that cannot pass _structures_ themselves both as arguments and as function results. The above holds for _arrays_, though; that is a basic (mis)feature of C (and C++). Of course, pointers to structures are very often used as arguments in practice: either a call-by-reference effect is desired or copying large structures would appear inefficient. > For the results of external functions, the Eiffel > compiler can take care of ensuring the proper semantics > (copy for expanded, reference for unexpanded); a language- > dependent convention is needed, however, to determine what > the function will return. In C, the answer is the only > portable one: the C function is assumed to return a pointer > to the result for non-basic types, expanded or not. The > code generated by the Eiffel compiler then takes care of > performing a copy in the expanded case. > Returning a pointer (to a struct or an array) as the result of a C (or C++) function is very dangerous and should be done only if its referent (the _object pointed to_) fulfills one of the conditions: 1. its storage class is static or extern; 2. its storage class is auto, but it is defined in a calling function; 3. it has been allocated in dynamic memory before calling the function (and hopefully "someone" will delete it when it is no longer needed); 4. it has been allocated in dynamic memory within the function and its remaining allocated will not cause too much memory shortage (there is no garbage collection in the C or C++ realm). The most important point is: never pass a pointer to an _automatic_ variable of a function as the result of that function (cf. my short article in ACM SIGPLAN Notices, March 1989)! My recommendation for most cases is therefore: A. Pass any structure _itself_ (not a pointer to it) as the function's result. B. Since it is impossible to pass an _array_ itself, declare a structure that has the array as its only element; C (or C++) will let you pass the structure. This is only a compile-time trick that adds nothing to the runtime objects, so the Eiffel side should be able to handle the result directly as an (expanded?) array. Probably there _are_ cases in which one would rather like to pass a pointer as the result, especially with arrays. One must then be very careful. Markku Sakkinen Dept. of Computer Science, University of Jyvaskyla (imagine the a's in 'Jyvaskyla' with umlauts)