!topic LSN on Export -- Elaboration Issues !key LSN-1074 on Export -- Elaboration Issues !reference RM9X-M.1;4.0 !from Bob Duff $Date: 94/02/05 11:35:29 $ $Revision: 1.3 $ !discussion At the recent DR/XRG meeting in the UK, it was recognized that there is a hole in the Ada 9X support for pragma Export. This LSN proposes to plug that hole. The purpose of pragma Export is to allow Ada subprograms to be called from another language. (It also allows other entities, mainly variables, to be accessed from another language.) This works fine if the main subprogram is written in Ada, which then calls, say, some C code, which then calls back into Ada code. However, if the "main subprogram" is written in C, it is impossible to call an Ada subprogram, because that subprogram will not have been elaborated yet. It will raise Program_Error, by 3.11(6). In C, it is possible to write a set of library routines, and to call them from any language. The same functionality should be available in Ada. The fact that a certain package happens to be written in Ada should not imply that the main subprogram must also be written in Ada. Therefore, we propose to add the following Implementation Advice to Annex M: If an implementation supports pragma Export, then it should also allow the main subprogram to be written in the other language. It should support some mechanism for invoking the elaboration of the Ada library units included in the system, and for invoking the finalization of the environment task. On typical systems, the recommended mechanism is to provide two subprograms whose link names are "adainit" and "adafinal". Adainit should contain the elaboration code for library units. Adafinal should contain the finalization code. These subprograms should do nothing the second and subsequent time they are called. Thus, if the main subprogram is written in C, it can call adainit before it makes its first call to an Ada subprogram, and adafinal after the last. Note that there is no point in defining an Ada name for these subprograms, since they do not need to be called from Ada code. Note that there is no requirement for an Ada implementation to support mixed-language programming. If the Ada implementation wants to control the entire machine (on an Ada-only embedded system, for example), there is no need to support this feature (or pragma Export). Note that there may be interactions between languages. Such interactions are, of course, implementation dependent. For example, an implementation of Ada tasks might interact with some implementation of threads. An implementation can always state that certain combinations won't work. For example, an implementation might state that you can't use threads and Ada tasks in the same program. A different implementation might go to the trouble to map Ada tasks to threads one-for-one. In any case, since any interactions between languages are necessarily implementation dependent, such interactions cannot be the basis of an argument against any interfacing feature. Some have expressed concern over implementation burden. In particular, the implementation's startup code might have to be restructured in order to support the adainit feature. On some systems, initialization of the run-time system would occur in adainit before elaborating normal library units. On others, at least part of the initialization might need to occur separately (before the other-language main subprogram gets control). In particular, initialization of hardware resources often needs to happen early. Whether that code executes upon booting up the computer, or under control of an operating system, or in some other way is up to the implementation to decide. Such a reorganization of startup code seems feasible, and worth the benefit of better interoperability with other languages. The implementation will also have to separate the code that does library unit elaboration from the code that calls the main subprogram. However, implementations will need to make that separation anyway, since Ada 9X no longer requires there to even *be* a main subprogram. It is beneficial to make the link names standard. We have purposely chosen names that are less than or equal to 8 characters in length, since that is portable to most systems. More elaborate ideas have also been suggested. For example, it would be convenient if "adainit" were called automatically just before the first time an Ada subprogram is entered. However, this introduces some difficulties: - It is not clear exactly which library units should be elaborated for a given subprogram call. - Existing implementations might find it difficult to support the feature at this fine granularity. Such a feature might interact with an implementation's efforts to optimize away elaboration checks. - It might be less efficient. People already complain that Ada has the extra overhead of elaboration checks. An additional check might exacerbate that problem. Note that some implementations use special mechanisms to implement elaboration checks efficiently, such as indirect calls, so it might not be feasible to fold in the new check with the existing one. - Implementations are free to support such functionality if they want. Calling adainit explicitly after it has already been called implicitly is harmless. Hence, we propose what we believe to be the minimal feature that solves the problem. It does mean that the C code has to do something "extra" (namely to call adainit and adafinal). However, this seems like a small burden on a programmer who is not writing in "pure" Ada anyway.