The situation is as follows.
There is a function (in a separate file) whose behavior depends on the external variable. This function should be called from programs that set the value of this variable, and programs that do not know anything about this variable (and do not want to know).
I have to say that if the function is translated by gcc -c, then there is no problem. Any C as well as C ++ programs normally work with it.
I just tried to compile it with C ++ (of course, it will work only with C ++ programs) and there was a problem:
ext-po:(.bss+0x0): multiple definition of `extext' /tmp/ccLZRaiS.o:(.data+0x0): first defined here collect2: ld returned 1 exit status Here are the files:
// ext.h extern const char *extext; #ifdef __cplusplus extern "C" { #endif int ptext (const char *t); #ifdef __cplusplus } #endif This header file is included in all programs that call ptext() .
// ext-pc та самая внешняя функция #include <stdio.h> #include "ext.h" const char *extext; int ptext (const char *p) { return puts (p ? : extext ? : "nothing to print"); } The point is that if the external module does not use extext, then its value will be NULL.
A couple of programs calling the function.
// ext-mc.c #include <stdio.h> #include "ext.h" #ifndef __cplusplus const char *extext = "text test"; #else const char *extext = "c++ text test"; #endif int main (int ac, char *av[]) { ptext(av[1]); } ext-mc.c sets the value to etext , and the next one doesn't want to know anything about it.
// ext-mc #include <stdio.h> #include "ext.h" int main (int ac, char *av[]) { ptext(av[1]); } Compilation and Run Protocol
avp@avp-xub11:avparse$ gcc ext-pc -c avp@avp-xub11:avparse$ g++ ext-mc.c ext-po avp@avp-xub11:avparse$ ./a.out c++ text test avp@avp-xub11:avparse$ gcc ext-mc.c ext-po avp@avp-xub11:avparse$ ./a.out text test avp@avp-xub11:avparse$ g++ ext-mc ext-po avp@avp-xub11:avparse$ ./a.out nothing to print avp@avp-xub11:avparse$ gcc ext-mc ext-po avp@avp-xub11:avparse$ ./a.out nothing to print avp@avp-xub11:avparse$ It can be seen that when the file with ptext() translated by gcc everything works as intended.
avp@avp-xub11:avparse$ g++ ext-pc -c avp@avp-xub11:avparse$ g++ ext-mc ext-po avp@avp-xub11:avparse$ ./a.out nothing to print avp@avp-xub11:avparse$ g++ ext-mc.c ext-po ext-po:(.bss+0x0): multiple definition of `extext' /tmp/ccLZRaiS.o:(.data+0x0): first defined here collect2: ld returned 1 exit status avp@avp-xub11:avparse$ Actually, the question is the same as in the title - Does anyone know how to program such a thing , so that everything can be compiled and gcc and g ++?
Update 1
Judging by the suggestions in some of the comments, probably in the question I didn’t highlight the problem enough.
There is a function (actually not the one shown in the example), which is used in many programs and is not called directly from main. It displays the contents of a certain structure (one of its parameters).
It is desirable that the additional information (constant for the program text - the author, version, etc.) does not need to be “dragged” from main (), where it is naturally defined before this function.
If the function is translated by gcc and is in the library, then everything is OK. There are no problems with C, nor with C ++ programs and the way of specifying this information in them (as in the example in question, you can just write main at the beginning of the text extext = "bla-bla .." or even read from the config, etc. P.).
If the programmer takes the .c file with it and collects the program (g ++) along with his other .cpp files and does not explicitly state in the Makefile that it should be compiled with gcc -c, then the described error occurs.
The question, and this is generally implemented in C ++, remains.
Update 2 (look @mikillskegg appeared)
Now we see the following picture:
avp@avp-ubu1:avparse$ gcc -c ext-pc; nm ext-po 0000000000000008 C extext 0000000000000000 T ptext U puts avp@avp-ubu1:avparse$ g++ -c ext-pc; nm ext-po 0000000000000000 B extext 0000000000000000 T ptext U puts avp@avp-ubu1:avparse$ Maybe the solution will work if you answer this question:
How do you write ext-pc , so that in the output nm ext-po instead of B extext you get C extext ?
#definehas nothing to do with it. Probably in the question I did not highlight the problem. There is a function (actually not the one shown in the example), which is used in many programs and is not called directly frommain. It displays the contents of a certain structure (one of its parameters). It is desirable that the additional information (constant for the program text - the author, version, etc.) does not need to be “dragged” frommain(), where it is naturally defined before this function. - (there is little space, I will continue in the next commentary) - avp