gas@cs.nott.ac.uk (Alan Shepherd) (04/22/91)
About a week ago I posted an article asking for help with a problem I
was having with making C++ functions (not methods) callable from C++.
I've had quite a response so I thought other people might be
interested in the necessary details. The first thing to do is to
declare your C++ function to have C linkage (even though you compile
it with C++) e.g.
extern "C" void aC++Fn();
void aC++Fn()
{
cout << "A C++ Function" << endl;
}
This is the easy bit. The second step involves linking using C++ and
not C. Most of my replies pointed this out, but I had done this and
still encountered problems (sorry for not pointing this out before).
The crucial step is that the file with main() needs to be compiled
using C++ even if it is in a c file. Thanks to those people who
pointed this out.
I felt a bit of an idiot when I realised the solution, but several of
my replies missed this too, so I don't feel quite so bad....:-)
Alan Shepherd
strollo@ssd.kodak.com (larry strollo ) (04/23/91)
In article <1991Apr22.064847.16929@cs.nott.ac.uk> gas@cs.nott.ac.uk () writes: >> >> I've had quite a response so I thought other people might be >> interested in the necessary details. ...... particulars deleted ........ >> >> This is the easy bit. The second step involves linking using C++ and >> not C. Most of my replies pointed this out, but I had done this and >> still encountered problems (sorry for not pointing this out before). I'm confused. Since the linker is just linking object files (generated from C I might add), what is special about the C++ "linker" ? Do you really mean that some special C++ libraries are linked in (in which case I should be able to do the same thing by just explicitly calling out the libraries in the link command, shouldn't I) ? >> The crucial step is that the file with main() needs to be compiled >> using C++ even if it is in a c file. Thanks to those people who >> pointed this out. >> I'm working on a set of programs that are going to be implemented in C++, but must provide an interface callable from C. It's probably not going to be reasonable for me to insist that the user have Cfront. Am I in trouble ? >> I felt a bit of an idiot when I realised the solution, but several of >> my replies missed this too, so I don't feel quite so bad....:-) >> >> Alan Shepherd >> >> Not nearly as bad as I'm going to feel if the answer to my last question is "yes" ! |8-} Larry Strollo strollo@ssd.kodak.com] -- ------------------------------------------------------------------------------ Larry Strollo strollo@ssd.kodak.com (716) 726-0901 Integration & Systems Products Division Eastman Kodak Co Rochester NY ------------------------------------------------------------------------------
steve@taumet.com (Stephen Clamage) (04/24/91)
strollo@ssd.kodak.com (larry strollo ) writes: >In article <1991Apr22.064847.16929@cs.nott.ac.uk> gas@cs.nott.ac.uk () writes: >>> This is the easy bit. The second step involves linking using C++ and >>> not C. Most of my replies pointed this out, but I had done this and >>> still encountered problems (sorry for not pointing this out before). >I'm confused. Since the linker is just linking object files (generated from >C I might add), what is special about the C++ "linker" ? Usually linking is done via the cc or CC driver program (or whatever it is called on your system). The C++ version of the driver (or the driver when told to operate in C++ mode) does different things for C++ than for C. If you know the ultimate linking command, you can use that command directly, if less conveniently. Sometimes the C++ driver runs separate post-linking commands, which you would have to remember to do as well. >I'm working on a set of programs that are going to be implemented in C++, >but must provide an interface callable from C. It's probably not going to >be reasonable for me to insist that the user have Cfront. Am I in trouble ? Not necessarily. All C++ compilers I am familiar with require that main() be compiled with with the C++ compiler. This does not mean that the user must have a C++ compiler to use your programs. You write the actual main() in its own module like this: extern int my_main(int, char**); main(int argc, char** argv) { return my_main(argc, argv); } Compile it with the C++ compiler, and put it in your library. Instruct your users to write their main() with the name "my_main" instead. Everything should just work. In some cases, the user might want main() to take additional parameters, one common variation being main(int argc, char** argv, char** environment) You might have to provide several versions of main() in that case, and at most one of them could be put into a library; the others would have to be separate object files. -- Steve Clamage, TauMetric Corp, steve@taumet.com
cooker@newsrice.edu (Donald George Baker) (04/24/91)
In article <1991Apr23.133931.6716@ssd.kodak.com>, strollo@ssd.kodak.com (larry strollo ) writes: |> |> I'm confused. Since the linker is just linking object files (generated |> from C I might add), what is special about the C++ "linker" ? Do you |> really mean that some special C++ libraries are linked in (in which case I |> should be able to do the same thing by just explicitly calling out the |> libraries in the link command, shouldn't I) ? I can see that there is still a lot of confusion about what is happening with the C++ linker and how it relates to mixing in pure C code. Besides linking against the C++ library, the linker does the interesting part of getting the constructors and destructors for global objects called at the right time. Note: these comments refer to AT&T's CFront, so your milage may vary. The C++ linker actually links a program twice. The first time to make an executable on which 'nm' can be run. The second pass looks for routines that follow a particular naming convention. These routines are the constructors and destructors for global objects. The routines are gathered up and put into two tables. The order in which these appear is totally dependent on the linking order--a serious problem with global objects. A routine called _main will call all of the constructors and _exit (I think) calls all of the destructors. It is hard not to have the destructors called, because you must link against the special _exit, but when your main program is not C++, _main does not get called automatically. All you need to do is call _main() with no arguments yourself. I hope this helps. ----------------------------------------------------------------------------- Donald G. Baker (cooker@Rice.edu) \ Computer Science Department, Computer-human interaction, \ Rice University Programming environments, /\ P. O. Box 1892 Software engineering / \ Houston, TX 77251-1892, USA ----------------------------------------------------------------------------- -- ----------------------------------------------------------------------------- Donald G. Baker (cooker@Rice.edu) \ Computer Science Department, Computer-human interaction, \ Rice University Programming environments, /\ P. O. Box 1892
pauld@stowe.cs.washington.edu (Paul Barton-Davis) (04/25/91)
As an example of what the "C++ linker" does that the "C linker" does not: AT&T C++ 2.1 comes in two varieties, one called patch, the other called munch. The patch version edits the object file produced by the linker to fill in the addresses used to link the statics ctors and dtors together. The munch version does this by running the link editor/loader (whatever) twice. Getting this functionality yourself is tedious, but obviously could be done, especially since the "patch" code is a separate process run by the CC script. -- Paul Barton-Davis <pauld@cs.washington.edu> UW Computer Science Lab "People cannot cooperate towards common goals if they are forced to
steve@taumet.com (Stephen Clamage) (04/25/91)
steve@taumet.com (Stephen Clamage) writes: >You write the actual main() in its own module like this: > extern int my_main(int, char**); > main(int argc, char** argv) > { > return my_main(argc, argv); > } >Compile it with the C++ compiler, and put it in your library. Instruct >your users to write their main() with the name "my_main" instead. >Everything should just work. Oops! I forgot two very important points. 1. Unless you supply the C++ runtime library and any special startup modules (some systems provide a replacement crt0.o or equivalent), or you will have to pre-link your entire library with the C++ runtimes and supply it as a single object module. Otherwise, things may turn up missing when a user tries to link a program. 2. Most C++ implementations require steps to be done after linking. (Cfront requires "patch" or "munch", Oregon C++ requires "cdlink".) Any application with static objects requiring constructors or destructors (such as stream I/O) will require this step. You will have to experiment to see if the step can be omitted when there are no static objects. -- Steve Clamage, TauMetric Corp, steve@taumet.com
joe@proto.com (Joe Huffman) (04/27/91)
steve@taumet.com (Stephen Clamage) writes: >Not necessarily. All C++ compilers I am familiar with require that >main() be compiled with with the C++ compiler. This does not mean You must not be familiar with the Zortech Compiler. It does not have that requirement. -- joe@proto.com