Reputation: 20420
I'm using static library that produces std output using printf(). How can i intercept it in order to show the output in my app and do some highlighting for example?
I have the sources of the lib and i can modify it slightly if needed.
Upvotes: 1
Views: 2438
Reputation: 42845
I have the sources of the lib and i can modify it slightly if needed.
Well, if you're really sure they're using printf
, and you can build their code, you can use that against them so long as you don't have other places in there that use printf
.
(I'm assuming a Unix-like platform, so there might need to be some modification to get this to work elsewhere.)
One thing you can do is redefine printf
to point to your own version. Another is to write your own printf
and link it in before the standard libraries. Neither of these routes are really what you'd consider recommended practice, though they should work. Neither route requires modification of the source of the library.
Here we just mess with the compiler's concept of printf
by telling it that it's really a different function. Add something like this to your Makefile:
CFLAGS += -Dprintf=redirected_printf
CXXFLAGS += -Dprintf=redirected_printf
(Some build systems use the variable DEFINES
for this purpose; YMMV.)
This tells the compiler to replace every instance of the identifier printf
with redirected_printf
. It's the same as if you put #define printf redirected_printf
at the top of every source file.
Now you just need to write the redirected_printf
function. I prefer to pass the formatting off to another function in stdio, vasprintf
, which does the same thing as printf
except it takes a va_list
instead of ...
and returns a pointer to a heap-allocated string with the output.
#include <stdarg.h>
#include <stdio.h>
extern "C" int redirected_printf(const char * format, ...) {
// Make formatted string.
char* outstr = 0;
va_list ap;
va_start(ap, format);
int result = vasprintf(&outstr, format, ap);
va_end(ap);
if(result < 0) // Error occurred and `outstr` undefined if result < 0.
return result;
// Do something with the string in `outstr` here, like display it in a dialog.
// Clean up and return.
free(outstr);
return result;
}
This is a bit trickier, because you have to write a function named printf
that works like replacement_printf
above, and then you have to convince the linker to link to your version instead of the standard library's. You might be able to just stick your printf
in one of your compilation units and be done with it; when the clinker links the library you're redirecting to your sources, it will find your printf and link to it; then later when it sees the one in the standard library, it will just drop it because at that point nothing calls it.
If that doesn't work, you can try to put your printf
into a library of your own with the ar
and ranlib
commands, then link that library after the one you're redirecting.
Note that if this library you're trying to redirect is a shared library (like a DLL or .so file), this probably won't work; it was linked to the standard printf
back when it was built.
This route has a lot more caveats and depends on just how your linker works and a bunch of other things, so I don't recommend it, but I'm including it here for completeness.
Upvotes: 3
Reputation: 20420
i was able to do it using freopen(..);
:
http://www.cplusplus.com/reference/cstdio/freopen/
Upvotes: 1