472,122 Members | 1,548 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,122 software developers and data experts.

How to override standard printf defined in gcc library

Hi,

I am Rahul. We have a complete software written out (with n other shared libraries maintained by various other teams). The shared libraries are loaded at run time by the main executable depending upon what feature user wants to run. All across our code, we are using printf and fprintf to print messages on the screen for the user. Now, we are adding a Graphical interface to our software and require that all such messages are displayed in a separate window inside that Graphical interface (whenever user is running in Graphical mode, else messages should be printed to screen only). For this, we need to overload printf and fprintf in our code. We have a combination of C and C++ code, as well as due to vast code base distributed across teams, it is not possible to replace printf/fprintf in all the code with some other function. So, what we did, we defined our own printf and fprintf functions that look something as follows -

Expand|Select|Wrap|Line Numbers
  1. extern "C" int fprintf (FILE *__restrict __stream,
  2.         __const char *__restrict __format, ...)
  3. {
  4.     va_list args;
  5.  
  6.     va_start(args,__format);
  7.  
  8.     int return_status = 0;
  9.     if (is_gui && (__stream == stdout || __stream == stderr)) {
  10.         return_status = showMessageInGui(NULL, __format, args);
  11.     }
  12.     else {
  13.         return_status = vfprintf(__stream, __format, args);
  14.     }
  15.  
  16.     va_end(args);
  17.     return return_status;
  18. }
  19.  
Above function is defined in main executable (where our main() lies). So, above definition is loaded before fprintf from gcc library is loaded. I guess, no fprintf should be picked from libgcc now.
Above code works fine for following fprintf calls (that pass variable argument list to fprintf) -

fprintf (stdout,"This is a variable argument message - %s\n", "Rahul Jain");

However, for following fprintf call (that is not taking any variable arguments), it seems fprintf from libgcc is getting picked up as then print comes on the screen instead of our Graphical interface window -

fprintf (stdout,"This is a variable argument message - Rahul Jain\n");

I am not sure why this is happening. Is fprintf implemented as macro, such that it is working for case1 and not for case2. Can anybody help.

I would be really greateful if someone can help me and reply as soon as possible, we have a hight priority delivery item and is very critical... Really appreciate your help guys.
Oct 27 '09 #1
9 24174
Banfa
9,065 Expert Mod 8TB
fprintf (and printf) are in the standard C library. This is a static library. You can replace any function in the standard library by writing your own version and compiling it and then linking with the object. The linker will prefer the version in your object file to the version in the library. The library is only used to resolve symbols that have not been resolved in all the object files of the program.

However when a shared library is created all its static symbols would be resolved in its own link stage. In order to get all your output redirected in this way you would need to link every shared object and executable with the file containing the alternate fprintf and printf.

Another option might be to redirect stdout, for instance using freopen, however I am not a Linux guru and do not know if shared libraries use the same output streams as their calling executables or if they have their own copy (which would be a problem with this suggestion).
Oct 27 '09 #2
weaknessforcats
9,208 Expert Mod 8TB
You are not really overloading anything. An overload means two functions have the same name but different argument lists.

Here your printf and fprintf have the same name and argument list but diffrerent guts. This is an override. Unfortunately, C provides no way to prefer your functions to the standard functions since you cannot override functions in C.

Your only solution will be to not use the standard library at all. Instead, since the source code to all the standard functions is publicly available, make a copy of it all, chang the printf and fprintf to be what you your want and then create a new library with a new name. Then recompile and relink all of your C/C++ code.

Lastly, make it a firing offense to use the C standard library directly.

In the long run you will be better off not using C functions at all. Instead there should be a C++ class that does the output for you. You install that class in your C code (which now becomes C++ code) and recompile. You will be totally on C++, your output will always go th the correct place and the notion of a graphical mode would go away.
Oct 27 '09 #3
Hi,

Thanks guys for your replies.. Yes, you people are right that what I want to achieve is actually overriding (and not overloading, i used that term in my question mistakenly). But, it is not exactly an overriding as I am loading libgcc as a shared library. If we look at the way by which the loader resolves various symbols on loading an application, it does something as follows -

1. Load symbols defined and already binded in the executable
2. Load the shared library on which the application depends and then resolve the still undefined symbols in the application.

In my case, loader finds that fprintf/printf are already defined in my executable, so it should not lookup for this function while loading gcc shared library.

It seems to be the case as in case#1 (with variable argument list given to fprintf my own version is getting called). This does not happens for case #2 however.

I have also narrowed down that this issue comes with gcc 4.2.4 and not with gcc 3.4.2.

You can easily reproduce this issue by creating a printf.c and defining your version of fprintf in it and calling it from main (defined in main.c)

Does anyone know if any changes made between gcc 342 and gcc 424 that might be causing this issue, and if there is any workaround to it by some build time flags.

Once again, thanks guys for your replies.
Oct 27 '09 #4
newb16
687 512MB
@weaknessforcats
And then contact company's IP lawyer to determine if you need to release under GPL all of your code or only modified stdlib.
Oct 28 '09 #5
@RahulJain83
I'm doing GCC on Cygwin. You mention a GUI. What is it called, and where do I get it? Many thanks, JonB
Nov 3 '09 #6
Ectara
24
If you are fine with macros, you could #define in one of your main headers to change fprintf and printf to functions that you name, and use the same argument list.

And Jon, I'm not sure of the protocol, but that probably should have gone in a PM.
Nov 3 '09 #7
try using "nm" command ... in linux.. doing "man nm" would say like... it lists all the symbols in the object file.... So what i did.. was... i modified a bit of your code.. and tried using it in my code.. compiled it... and.. used nm <objectfilename> to see.. whtat's the result......

$ nm a.out
<it gave a lot many lines... bt i would like to mention only a few>
08048484 T fprintf
08048460 t frame_dummy
080484f7 T main

0804a020 B stderr@@GLIBC_2.0
0804a040 B stdout@@GLIBC_2.0
U vfprintf@@GLIBC_2.0

for first and second column read man of nm... the third column is what we can see for you query...
as fprintf has been defined in the source code.. so no extra symbol defining.. where to link it has been mentioned... which can be seen in stderr@@GLIBC_2.0 , stdout@@GLIBC_2.0 and vfprintf@@GLIBC_2.0.. which tells the system.. to where to look for this external symbols!!!

I hope.. usign nm can help you in understanding.. what your source code is actually using.. after becoming a object file....

Other useful command can be.. objdump.. which I haven't used... so.. please try it by yourself... and post any reply!! if that was useful in your case!!
Nov 21 '09 #8
weaknessforcats
9,208 Expert Mod 8TB
Keep in mind as you progress in the effort that if things keep getting more and more complicated, you are on the wrong track.

In fact you are on the wrong track.

At some point you will revert to using the printf from C and renaming yours. This is the whol reason static functions were out into C. It was to isolate your name conflicts from the system.

In C++ you use namespaces for this. My printf is MyStuff::printf and this is clearly different from just the C printf. You will need to call MyStuff::printf to get your printf and just printf to get the C standard printf.

I assume there is someone there that knows how to implement a namespace. Otherwise, let me know and I'll go over it here.
Nov 23 '09 #9
RRick
463 Expert 256MB
I tried a similar test on my linux box using g++ 4.2.4 and it works fine for all cases. To test out the C lib fprintf, just change the method's name to xxxfprintf.

This makes me think that there is something missing in your checking for stdout and stderr. I'm not 100% certain, but if something is piped between processeses or copied or whatever, it might act like a stdout, but not be the same stdout.

Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2. #include <iostream>
  3.  
  4. extern "C" int fprintf( FILE * file, const char * format, ...)
  5. {
  6.     va_list args;
  7.  
  8.     va_start( args, format);
  9.  
  10.     std::string fstr( std::string( "Got It:  ") + format + "\n");
  11.  
  12.     int status =  vfprintf( file, fstr.c_str(), args);
  13.  
  14.     va_end(args);
  15.  
  16.     return status;
  17. }
  18.  
  19.  
  20.  
  21. int main()
  22. {
  23.      fprintf( stdout, "xxx\n");
  24.      fprintf( stdout, "xxx %s\n", "yyy");
  25.      return 0;
Nov 23 '09 #10

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

71 posts views Thread by Christopher Benson-Manica | last post: by
39 posts views Thread by Jim Showalter | last post: by
2 posts views Thread by Nishu | last post: by
4 posts views Thread by MisterE | last post: by
126 posts views Thread by Dann Corbit | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.