AdaIC News Winter 1995

How Can I...?

A new feature of the AdaIC NEWS.


What do you do when your code doesn't act the way you expect it to? What do you when no one can answer that language-lawyer question? What do you do when you suspect "there has to be an easier way to do this?" Where do you turn when you and everyone you work with runs out of answers?

Well, if you have access to the Internet, one possibility is comp.lang.ada - one of the n thousand "newsgroups" in USENET. If your Internet host takes the command readnews or rn or vn or nn or vnews, you may have access to comp.lang.ada - and thereby to Ada users around the world.

For those of you on the Internet without USENET access, there's an alternative via e-mail- info-ada mailing list. To add your name to the list, send an e-mail message to listserv@vm1.nodak.edu. The body should contain the line

    subscribe info-ada [your full name]

Here, [your full name] is your name, not your net address. If you have any questions, contact the AdaIC for information.

In future issues, we hope to bring you samples of the Ada-programming discussions that take place on comp.lang.ada.

A recent thread (subject) shows comp.lang.ada at work: a succint question, a fast reply, and other comments that give you things to think about.

The question

On Thu, 3 Nov 1994 12:53:31 GMT, Chris Vanover at the University of Alabama, posted a question on "Calling C++ from within ADA":

Is there a way to call a C++ procedure from within ADA? I can call a C procedure with


	package C_LIB is

		procedure clear_screen;

		procedure sleep_a_moment;

	private

		pragma interface(c,clear_screen);

		pragma interface(c,sleep_a_moment);

	end C_LIB;

However, when I compile the same C procedure in C++ I get the following error:


	0706-317 ERROR: Unresolved or undefined symbols detected:
Symbols in error (followed by references) are dumped
to the load map. The -bloadmap: option will create
a loadmap.
.clear_screen

I've tried adding INTERFACE_INFORMATION but it doesn't seem to help. I am using IBM AIX on an RS6000.

A reply

Less than three hours later, Norman H. Cohen at IBM's T.J. Watson Research Center posted a reply:

The error message comes from the linker, ld, which is invoked by the compiler when you compile with -b or -m (to construct an executable main program). I suspect that your C++ compiler is creating a "mangled" external name for clear_screen, rather than the name .clear_screen created by your C compiler. Use the AIX nm command to see the external symbols in the .o file produced by your C++ compiler, and, if you can figure out which one is a mangled name for clear_screen, adjust your Interface_Information pragma accordingly.

An addition

Around 9 hours after Norm Cohen's reply was posted, Keith Thompson at Alsys commented on it, adding:

Or better yet, declare the C++ functions with extern "C". (Theoretically you could use extern "Ada", but I doubt that any C++ compilers support it; support for extern "C" is mandatory.) Depending on a particular C++ compiler's name mangling algorithm probably isn't a very good idea.

And another

And shortly after the start of business on the next Monday, a comment came from Oliver E. Cole at OC Systems, Inc.- the company that now handles the IBM Ada compiler. It said simply:

Norm Cohen was right in his response.

Please feel free to contact us at info@ocsystems.com if you have questions. We support our university users ...

And more

Was that the end of it?
No. On Tuesday the 8th, Eric Beser at NASA Goddard Space Flight Center replied:

We call C++ from Ada by doing the following.

If the C++ object has been created before calling Ada, A "This Ptr" needs to be passed to the Ada for the object that is to be called. The This Ptr points to the object of reference.

If other objects needed to be accessed, you can do it by getting other "This Ptr" pointers. The calling interface from Ada to C++ has to be to an extern "C" function.

However this function can be defined in the H file. The "This Ptr" is used to access class member functions from the calling interface.

The other rule is that no object can be called unless elaborated first. This includes Ada and C++.

Hope this helps.

And still more

And later that day, Richard G. Hash at Shell Bellaire Research Center commented:

Unless I'm missing something you've got a link problem - both Ada and C++ want control first (before main) for "elaboration" (and whatever C++ calls it). A normal (AIX) C++ application uses /bin/xlC to link, which actually creates a little tmp file with the cdtors table in it, and links it in (you can see this being generated by munch if you use "xlC -#").

You'll find that the crt0.o being linked in by C++ isn't the one in /usr/lib/crt0.o, it's in /usr/lpp/xlC/lib/crt0.o, and it has a call to "__C_runtime_startup()" in it.

We got around this by generating the ld script for the Ada program (using an Ada main), and then linking in the generated cdtors table and manually calling _C_runtime_startup () first thing in our Ada main (we were linking in a C++ Dynatext library).

Yes, it's ugly; no, it's not portable; no, I can't even guarantee it will always work (I just found _C_runtime_startup in crt0 and said "hmm, looks suspicious, wonder what happens if you call it?"). [He later added that this appears to get all the C++ "elaboration" constructors called correctly.]

If there is a cleaner solution then I would like to hear it....

And so?

Besides any interest you may have in calling C++, this comp.lang.ada thread makes a number of points. Among them: 1) The turnaround time can be very short. 2) Answers may be partial or may go slightly beyond your original question. 3) Different people may give you different approaches: You have to figure out which is best for you. (And we can add another: caveat lector. No credentials are required to post to an unmoderated news group like comp.lang.ada; submissions are not refereed. You have to judge the accuracy on your own.)
AdaIC News hub page